Create text layout abstraction (#163)
Caches operations like string splitting and measuring.
This commit is contained in:
parent
0503166d05
commit
40be11f82c
@ -0,0 +1,46 @@
|
||||
package com.jakewharton.mosaic.text
|
||||
|
||||
import de.cketti.codepoints.codePointCount
|
||||
|
||||
internal class TextLayout {
|
||||
var value: String = ""
|
||||
set(value) {
|
||||
if (value != field) {
|
||||
dirty = true
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
var width: Int = -1
|
||||
private set
|
||||
get() {
|
||||
check(!dirty) { "Missing call to measure()" }
|
||||
return field
|
||||
}
|
||||
|
||||
var height: Int = -1
|
||||
private set
|
||||
get() {
|
||||
check(!dirty) { "Missing call to measure()" }
|
||||
return field
|
||||
}
|
||||
|
||||
var lines: List<String> = emptyList()
|
||||
private set
|
||||
get() {
|
||||
check(!dirty) { "Missing call to measure()" }
|
||||
return field
|
||||
}
|
||||
|
||||
private var dirty = true
|
||||
|
||||
fun measure() {
|
||||
if (!dirty) return
|
||||
|
||||
val lines = value.split('\n')
|
||||
width = lines.maxOf { it.codePointCount(0, it.length) }
|
||||
height = lines.size
|
||||
this.lines = lines
|
||||
dirty = false
|
||||
}
|
||||
}
|
||||
@ -3,8 +3,9 @@
|
||||
package com.jakewharton.mosaic.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.jakewharton.mosaic.layout.Layout
|
||||
import de.cketti.codepoints.codePointCount
|
||||
import com.jakewharton.mosaic.text.TextLayout
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
@Composable
|
||||
@ -14,18 +15,19 @@ public fun Text(
|
||||
background: Color? = null,
|
||||
style: TextStyle? = null,
|
||||
) {
|
||||
val layout = remember { TextLayout() }
|
||||
layout.value = value
|
||||
|
||||
Layout(
|
||||
debugInfo = {
|
||||
"""Text("$value")"""
|
||||
},
|
||||
measurePolicy = {
|
||||
val lines = value.split('\n')
|
||||
val width = lines.maxOf { it.codePointCount(0, it.length) }
|
||||
val height = lines.size
|
||||
layout(width, height)
|
||||
layout.measure()
|
||||
layout(layout.width, layout.height)
|
||||
},
|
||||
drawPolicy = { canvas ->
|
||||
value.split('\n').forEachIndexed { row, line ->
|
||||
layout.lines.forEachIndexed { row, line ->
|
||||
canvas.write(row, 0, line, color, background, style)
|
||||
}
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user