@@ -13,15 +13,28 @@ import androidx.compose.ui.node.LayoutNode
1313import androidx.compose.ui.text.TextLayoutResult
1414import kotlin.math.roundToInt
1515
16- internal class ComposeTextLayout (internal val layout : TextLayoutResult ) : TextLayout {
16+ internal class ComposeTextLayout (
17+ internal val layout : TextLayoutResult ,
18+ private val hasFillModifier : Boolean ,
19+ ) : TextLayout {
1720 override val lineCount: Int
1821 get() = layout.lineCount
1922
2023 override val dominantTextColor: Int?
2124 get() = null
2225
23- override fun getPrimaryHorizontal (line : Int , offset : Int ) =
24- layout.getHorizontalPosition(offset, usePrimaryDirection = true )
26+ override fun getPrimaryHorizontal (line : Int , offset : Int ): Float {
27+ val horizontalPos = layout.getHorizontalPosition(offset, usePrimaryDirection = true )
28+ // when there's no `fill` modifier on a Text composable, compose still thinks that there's
29+ // one and wrongly calculates horizontal position relative to node's start, not text's start
30+ // for some reason. This is only the case for single-line text (multiline works fien).
31+ // So we subtract line's left to get the correct position
32+ return if (! hasFillModifier && lineCount == 1 ) {
33+ horizontalPos - layout.getLineLeft(line)
34+ } else {
35+ horizontalPos
36+ }
37+ }
2538
2639 override fun getEllipsisCount (line : Int ): Int = if (layout.isLineEllipsized(line)) 1 else 0
2740
@@ -79,6 +92,8 @@ internal fun Painter.isMaskable(): Boolean {
7992 ! className.contains(" Brush" )
8093}
8194
95+ internal data class TextAttributes (val color : Color ? , val hasFillModifier : Boolean )
96+
8297/* *
8398 * This method is necessary to mask text in Compose.
8499 *
@@ -93,9 +108,10 @@ internal fun Painter.isMaskable(): Boolean {
93108 *
94109 * We also add special proguard rules to keep the `Text` class names and their `color` member.
95110 */
96- internal fun LayoutNode.findColor (): Color ? {
111+ internal fun LayoutNode.findTextAttributes (): TextAttributes {
97112 val modifierInfos = getModifierInfo()
98113 var color: Color ? = null
114+ var hasFillModifier = false
99115 for (index in modifierInfos.indices) {
100116 val modifier = modifierInfos[index].modifier
101117 val modifierClassName = modifier::class .java.name
@@ -111,9 +127,11 @@ internal fun LayoutNode.findColor(): Color? {
111127 } catch (e: Throwable ) {
112128 null
113129 }
130+ } else if (modifierClassName.contains(" Fill" )) {
131+ hasFillModifier = true
114132 }
115133 }
116- return color
134+ return TextAttributes ( color, hasFillModifier)
117135}
118136
119137/* *
0 commit comments