Create text layout abstraction (#163)

Caches operations like string splitting and measuring.
This commit is contained in:
Jake Wharton 2023-03-27 22:00:17 -04:00 committed by GitHub
parent 0503166d05
commit 40be11f82c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 6 deletions

View File

@ -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
}
}

View File

@ -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)
}
},