Supress text replacement spans for ellipsis

When a sequence of characters belonging to a text is ellipsized, we
usually replace the first characters with ... and then all the others
with a 0 width character, knowing that they will be drawn, but will be
invisible. However, these positions could have had ReplacementSpans
attached to them, such as EmojiTypefaceSpan when the EmojiCompat library
is used. When this happened, all the ellipsized out characters were
invisible, apart from emojis, which were still drawn as usual (as they
were replacing sequences of 0 width characters).
This CL fixes this behaviour, by skipping those ReplacementSpans that
were completely included in ellipsis. Please check the bug for a more
detailed explanation.

Bug: 69802699
Test: manual testing
Test: atest FrameworksCoreTests:android.text.TextLineTest
Change-Id: If9758537948abaa0226fe6b551a703110c5457b9
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 92f7a47..2367d63 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -562,7 +562,9 @@
                 // XXX: assumes there's nothing additional to be done
                 canvas.drawText(buf, start, end, x, lbaseline, paint);
             } else {
-                tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops);
+                tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops,
+                        getEllipsisStart(lineNum),
+                        getEllipsisStart(lineNum) + getEllipsisCount(lineNum));
                 if (justify) {
                     tl.justify(right - left - indentWidth);
                 }
@@ -1184,7 +1186,8 @@
         }
 
         TextLine tl = TextLine.obtain();
-        tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops);
+        tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops,
+                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         float wid = tl.measure(offset - start, trailing, null);
         TextLine.recycle(tl);
 
@@ -1223,7 +1226,8 @@
         }
 
         TextLine tl = TextLine.obtain();
-        tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops);
+        tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops,
+                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         boolean[] trailings = primaryIsTrailingPreviousAllLineOffsets(line);
         if (!primary) {
             for (int offset = 0; offset < trailings.length; ++offset) {
@@ -1365,7 +1369,8 @@
         final TextPaint paint = mWorkPaint;
         paint.set(mPaint);
         paint.setHyphenEdit(getHyphen(line));
-        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops);
+        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
+                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         if (isJustificationRequired(line)) {
             tl.justify(getJustifyWidth(line));
         }
@@ -1393,7 +1398,8 @@
         final TextPaint paint = mWorkPaint;
         paint.set(mPaint);
         paint.setHyphenEdit(getHyphen(line));
-        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops);
+        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
+                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         if (isJustificationRequired(line)) {
             tl.justify(getJustifyWidth(line));
         }
@@ -1478,7 +1484,8 @@
         TextLine tl = TextLine.obtain();
         // XXX: we don't care about tabs as we just use TextLine#getOffsetToLeftRightOf here.
         tl.set(mPaint, mText, lineStartOffset, lineEndOffset, getParagraphDirection(line), dirs,
-                false, null);
+                false, null,
+                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         final HorizontalMeasurementProvider horizontal =
                 new HorizontalMeasurementProvider(line, primary);
 
@@ -1732,7 +1739,8 @@
 
         TextLine tl = TextLine.obtain();
         // XXX: we don't care about tabs
-        tl.set(mPaint, mText, lineStart, lineEnd, lineDir, directions, false, null);
+        tl.set(mPaint, mText, lineStart, lineEnd, lineDir, directions, false, null,
+                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
         caret = lineStart + tl.getOffsetToLeftRightOf(caret - lineStart, toLeft);
         TextLine.recycle(tl);
         return caret;
@@ -2114,7 +2122,8 @@
                     break;
                 }
             }
-            tl.set(paint, text, start, end, dir, directions, hasTabs, tabStops);
+            tl.set(paint, text, start, end, dir, directions, hasTabs, tabStops,
+                    0 /* ellipsisStart */, 0 /* ellipsisEnd */);
             return margin + Math.abs(tl.metrics(null));
         } finally {
             TextLine.recycle(tl);