fix(icons): render Material Symbols with the correct tint

The painter measured the glyph with TextStyle(color = Unspecified) and
tried to override the color at draw time via drawText(layout, color = tint).
That override is unreliable across Compose versions: when the measured
style carries Color.Unspecified, drawText can fall through to Color.Black,
producing black-on-black icons (visible on the back arrow in dark mode).

Include the tint in the measured TextStyle directly. The (symbol, fontFamily,
density, tint, rtl) remember key on rememberMaterialSymbolPainter was already
keyed on tint, so the TextMeasurer cache still hits for every (symbol, color)
pair used by the app.
This commit is contained in:
Claude
2026-04-24 13:04:30 +00:00
parent 7ab23ce30e
commit 15e63c48a2
@@ -66,20 +66,22 @@ private class MaterialSymbolPainter(
override fun DrawScope.onDraw() {
val sizePx = size.minDimension
val fontSize = with(density) { sizePx.toSp() }
// TextStyle omits color; we override at draw time so TextMeasurer's cache hits across tints.
// Bake the tint into the measured style. drawText(color = ...) override is unreliable
// across Compose versions when the measured style has Color.Unspecified — falls back to
// Color.Black and produces black-on-black icons.
val layout =
textMeasurer.measure(
text = symbol.glyph,
style = TextStyle(fontFamily = fontFamily, fontSize = fontSize),
style = TextStyle(fontFamily = fontFamily, fontSize = fontSize, color = tint),
)
val tx = (size.width - layout.size.width) / 2f
val ty = (size.height - layout.size.height) / 2f
if (symbol.autoMirror && rtl) {
scale(scaleX = -1f, scaleY = 1f, pivot = Offset(size.width / 2f, size.height / 2f)) {
translate(tx, ty) { drawText(layout, color = tint) }
translate(tx, ty) { drawText(layout) }
}
} else {
translate(tx, ty) { drawText(layout, color = tint) }
translate(tx, ty) { drawText(layout) }
}
}
}