44import android .graphics .Paint ;
55import android .graphics .Path ;
66import android .graphics .RectF ;
7- import android .text .Spanned ;
8- import android .text .style . LeadingMarginSpan ;
7+ import android .text .StaticLayout ;
8+ import android .text .TextPaint ;
99import android .text .style .LineBackgroundSpan ;
1010
1111import androidx .annotation .ColorInt ;
@@ -18,11 +18,15 @@ public class MarkdownBackgroundSpan implements MarkdownSpan, LineBackgroundSpan
1818 private final int mentionEnd ;
1919 private final float borderRadius ;
2020
21+ private StaticLayout layout ;
22+ private Path backgroundPath ;
23+
2124 public MarkdownBackgroundSpan (@ ColorInt int backgroundColor , float borderRadius , int mentionStart , int mentionEnd ) {
2225 this .backgroundColor = backgroundColor ;
2326 this .borderRadius = borderRadius ;
2427 this .mentionStart = mentionStart ;
2528 this .mentionEnd = mentionEnd ;
29+ this .backgroundPath = new Path ();
2630 }
2731
2832 @ Override
@@ -39,36 +43,28 @@ public void drawBackground(
3943 int end ,
4044 int lnum
4145 ) {
42- int leadingMargin = getLeadingMargin (text , start , end );
46+ if (layout == null || layout .getText () != text || layout .getWidth () != right || layout .getLineEnd (0 ) != end ) {
47+ layout = StaticLayout .Builder .obtain (text , start , end , (TextPaint ) paint , right ).build ();
48+
49+ boolean mentionStarts = start <= mentionStart ;
50+ boolean mentionEnds = end >= mentionEnd ;
4351
44- boolean mentionStarts = start <= mentionStart ;
45- boolean mentionEnds = end >= mentionEnd ;
52+ float startX = layout . getPrimaryHorizontal ( mentionStarts ? mentionStart : start ) ;
53+ float endX = layout . getPrimaryHorizontal ( mentionEnds ? mentionEnd : end ) ;
4654
47- float startX = leadingMargin + (mentionStarts ? paint .measureText (text , start , mentionStart ) : 0 );
48- float endX = leadingMargin + paint .measureText (text , start , mentionEnds ? mentionEnd : end );
55+ RectF lineRect = new RectF (startX , top , endX , bottom );
56+ backgroundPath .reset ();
57+ backgroundPath .addRoundRect (lineRect , createRadii (mentionStarts , mentionEnds ), Path .Direction .CW );
58+ }
4959
5060 int originalColor = paint .getColor ();
5161 paint .setColor (backgroundColor );
5262
53- RectF lineRect = new RectF (startX , top , endX , bottom );
54- Path backgroundPath = new Path ();
55- backgroundPath .addRoundRect (lineRect , createRadii (mentionStarts , mentionEnds ), Path .Direction .CW );
5663 canvas .drawPath (backgroundPath , paint );
5764
5865 paint .setColor (originalColor );
5966 }
6067
61- private int getLeadingMargin (@ NonNull CharSequence text , int start , int end ) {
62- int leadingMargin = 0 ;
63- if (text instanceof Spanned spanned ) {
64- LeadingMarginSpan [] marginSpans = spanned .getSpans (start , end , LeadingMarginSpan .class );
65- for (LeadingMarginSpan marginSpan : marginSpans ) {
66- leadingMargin += marginSpan .getLeadingMargin (true );
67- }
68- }
69- return leadingMargin ;
70- }
71-
7268 private float [] createRadii (boolean roundedLeft , boolean roundedRight ) {
7369 float [] radii = new float [8 ];
7470
0 commit comments