Skip to content

Commit 2da0244

Browse files
cortinicometa-codesync[bot]
authored andcommitted
Fix text decoration color fallback to use per-span foreground color
Summary: D104680895 replaced `ReactUnderlineSpan`/`ReactStrikethroughSpan` with custom `CanvasEffectSpan` drawing, but when `textDecorationColor` is not explicitly set, it fell back to `layout.paint.color` (the base paint color, typically black) instead of the text's actual foreground color. This caused decorations to render in the wrong color for text with `ForegroundColorSpan` — e.g., white text on dark backgrounds got black underlines, teal link text got black underlines. This diff fixes the color by looking up the `ForegroundColorSpan` at the decoration's character position and using its color as the fallback instead of the base paint color. Changelog: [Android][Fixed] - Fix text decoration color not matching foreground color when `textDecorationColor` is not set Reviewed By: javache Differential Revision: D107645191 fbshipit-source-id: b1e0a616259c983ae57cdbf476ae97da4204d906
1 parent 319610d commit 2da0244

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextDecorationStyle.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import android.graphics.Paint
1414
import android.graphics.Path
1515
import android.os.Build
1616
import android.text.Layout
17+
import android.text.Spanned
18+
import android.text.style.ForegroundColorSpan
1719
import kotlin.math.max
1820
import kotlin.math.min
1921
import kotlin.math.roundToInt
@@ -126,7 +128,18 @@ internal fun drawSpannedDecoration(
126128
yOffsetForLine: (paint: Paint, baseline: Float, thickness: Float) -> Float,
127129
) {
128130
val textPaint = layout.paint
129-
val effectiveColor = if (color != Color.TRANSPARENT) color else textPaint.color
131+
val effectiveColor =
132+
if (color != Color.TRANSPARENT) {
133+
color
134+
} else {
135+
// Look up the actual foreground color at the span position. layout.paint
136+
// is the base paint whose color may differ from per-span foreground colors
137+
// applied via ForegroundColorSpan (e.g., link text, colored text).
138+
val spanned = layout.text as? Spanned
139+
val fgSpans = spanned?.getSpans(start, start + 1, ForegroundColorSpan::class.java)
140+
if (fgSpans != null && fgSpans.isNotEmpty()) fgSpans.last().foregroundColor
141+
else textPaint.color
142+
}
130143
val minThickness = 1.5f * textPaint.density
131144
val thickness =
132145
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

0 commit comments

Comments
 (0)