mirror of
https://github.com/JakeWharton/mosaic.git
synced 2025-11-02 04:36:19 +08:00
Use more efficient collections where possible (#483)
These avoid boxing, virtual calls, or both. Not all usages have been updated, just the easy targets.
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
[versions]
|
||||
compose = "1.6.11"
|
||||
kotlin = "2.0.20"
|
||||
kotlinx-coroutines = "1.9.0"
|
||||
mordant = "3.0.0"
|
||||
@ -11,7 +12,8 @@ kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotl
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
|
||||
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
|
||||
|
||||
compose-runtime = "org.jetbrains.compose.runtime:runtime:1.6.11"
|
||||
compose-collection = { module = "org.jetbrains.compose.collection-internal:collection", version.ref = "compose" }
|
||||
compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose" }
|
||||
|
||||
maven-publish-gradlePlugin = "com.vanniktech:gradle-maven-publish-plugin:0.29.0"
|
||||
dokka-gradlePlugin = "org.jetbrains.dokka:dokka-gradle-plugin:1.9.20"
|
||||
|
||||
@ -23,6 +23,7 @@ kotlin {
|
||||
dependencies {
|
||||
api libs.compose.runtime
|
||||
api libs.kotlinx.coroutines.core
|
||||
implementation libs.compose.collection
|
||||
implementation libs.finalizationHook
|
||||
implementation libs.mordant.core
|
||||
implementation libs.codepoints
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.jakewharton.mosaic
|
||||
|
||||
import androidx.collection.MutableIntList
|
||||
import androidx.collection.mutableIntListOf
|
||||
import com.jakewharton.mosaic.ui.AnsiLevel
|
||||
import com.jakewharton.mosaic.ui.Color
|
||||
import com.jakewharton.mosaic.ui.TextStyle
|
||||
@ -39,7 +41,7 @@ internal class TextSurface(
|
||||
|
||||
fun appendRowTo(appendable: Appendable, row: Int) {
|
||||
// Reused heap allocation for building ANSI attributes inside the loop.
|
||||
val attributes = mutableListOf<Int>()
|
||||
val attributes = mutableIntListOf()
|
||||
|
||||
val rowPixels = rows[row]
|
||||
var lastPixel = blankPixel
|
||||
@ -84,12 +86,14 @@ internal class TextSurface(
|
||||
maybeToggleStyle(Strikethrough, 9, 29)
|
||||
}
|
||||
if (attributes.isNotEmpty()) {
|
||||
attributes.joinTo(
|
||||
appendable,
|
||||
separator = ansiSeparator,
|
||||
prefix = CSI,
|
||||
postfix = ansiClosingCharacter,
|
||||
)
|
||||
appendable.append(CSI)
|
||||
attributes.forEachIndexed { index, element ->
|
||||
if (index > 0) {
|
||||
appendable.append(ansiSeparator)
|
||||
}
|
||||
appendable.append(element.toString())
|
||||
}
|
||||
appendable.append(ansiClosingCharacter)
|
||||
attributes.clear() // This list is reused!
|
||||
}
|
||||
}
|
||||
@ -107,7 +111,7 @@ internal class TextSurface(
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<Int>.addColor(
|
||||
private fun MutableIntList.addColor(
|
||||
color: Color,
|
||||
ansiLevel: AnsiLevel,
|
||||
select: Int,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.jakewharton.mosaic.layout
|
||||
|
||||
import androidx.collection.MutableObjectList
|
||||
import com.jakewharton.mosaic.TextCanvas
|
||||
import com.jakewharton.mosaic.TextSurface
|
||||
import com.jakewharton.mosaic.layout.Placeable.PlacementScope
|
||||
@ -95,7 +96,7 @@ internal class MosaicNode(
|
||||
val onStaticDraw: (() -> Unit)?,
|
||||
) : Measurable {
|
||||
val isStatic get() = onStaticDraw != null
|
||||
val children = mutableListOf<MosaicNode>()
|
||||
val children = ArrayList<MosaicNode>()
|
||||
|
||||
private val bottomLayer: MosaicNodeLayer = BottomLayer(this)
|
||||
var topLayer: MosaicNodeLayer = bottomLayer
|
||||
@ -150,8 +151,9 @@ internal class MosaicNode(
|
||||
* Append any static [TextSurfaces][TextSurface] to [statics].
|
||||
* A call to [measureAndPlace] must precede calls to this function.
|
||||
*/
|
||||
fun paintStatics(statics: MutableList<TextSurface>, ansiLevel: AnsiLevel) {
|
||||
for (child in children) {
|
||||
fun paintStatics(statics: MutableObjectList<TextSurface>, ansiLevel: AnsiLevel) {
|
||||
for (index in children.indices) {
|
||||
val child = children[index]
|
||||
if (isStatic) {
|
||||
statics += child.paint(ansiLevel)
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.jakewharton.mosaic
|
||||
|
||||
import androidx.collection.mutableScatterSetOf
|
||||
import androidx.compose.runtime.AbstractApplier
|
||||
import androidx.compose.runtime.BroadcastFrameClock
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -176,8 +177,8 @@ internal class MosaicComposition(
|
||||
|
||||
private val applyObserverHandle: ObserverHandle
|
||||
|
||||
private val readingStatesOnLayout = mutableSetOf<Any>()
|
||||
private val readingStatesOnDraw = mutableSetOf<Any>()
|
||||
private val readingStatesOnLayout = mutableScatterSetOf<Any>()
|
||||
private val readingStatesOnDraw = mutableScatterSetOf<Any>()
|
||||
|
||||
private val layoutBlockStateReadObserver: (Any) -> Unit = { readingStatesOnLayout.add(it) }
|
||||
private val drawBlockStateReadObserver: (Any) -> Unit = { readingStatesOnDraw.add(it) }
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.jakewharton.mosaic
|
||||
|
||||
import androidx.collection.mutableObjectListOf
|
||||
import com.jakewharton.mosaic.layout.MosaicNode
|
||||
import com.jakewharton.mosaic.ui.AnsiLevel
|
||||
import kotlin.time.ExperimentalTime
|
||||
@ -37,20 +38,18 @@ internal class DebugRendering(
|
||||
appendLine(node)
|
||||
appendLine()
|
||||
|
||||
val statics = mutableObjectListOf<TextSurface>()
|
||||
try {
|
||||
val statics = ArrayList<TextSurface>()
|
||||
.also { node.paintStatics(it, ansiLevel) }
|
||||
.map { it.render() }
|
||||
node.paintStatics(statics, ansiLevel)
|
||||
if (statics.isNotEmpty()) {
|
||||
appendLine("STATIC:")
|
||||
for (static in statics) {
|
||||
appendLine(static)
|
||||
statics.forEach { static ->
|
||||
appendLine(static.render())
|
||||
}
|
||||
appendLine()
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
failed = true
|
||||
appendLine("STATIC:")
|
||||
appendLine(t.stackTraceToString())
|
||||
}
|
||||
|
||||
@ -73,7 +72,7 @@ internal class AnsiRendering(
|
||||
private val ansiLevel: AnsiLevel = AnsiLevel.TRUECOLOR,
|
||||
) : Rendering {
|
||||
private val stringBuilder = StringBuilder(100)
|
||||
private val staticSurfaces = ArrayList<TextSurface>()
|
||||
private val staticSurfaces = mutableObjectListOf<TextSurface>()
|
||||
private var lastHeight = 0
|
||||
|
||||
override fun render(node: MosaicNode): CharSequence {
|
||||
@ -98,11 +97,15 @@ internal class AnsiRendering(
|
||||
}
|
||||
}
|
||||
|
||||
node.paintStatics(staticSurfaces, ansiLevel)
|
||||
for (staticSurface in staticSurfaces) {
|
||||
appendSurface(staticSurface)
|
||||
staticSurfaces.let { staticSurfaces ->
|
||||
node.paintStatics(staticSurfaces, ansiLevel)
|
||||
if (staticSurfaces.isNotEmpty()) {
|
||||
staticSurfaces.forEach { staticSurface ->
|
||||
appendSurface(staticSurface)
|
||||
}
|
||||
staticSurfaces.clear()
|
||||
}
|
||||
}
|
||||
staticSurfaces.clear()
|
||||
|
||||
val surface = node.paint(ansiLevel)
|
||||
appendSurface(surface)
|
||||
|
||||
@ -116,9 +116,9 @@ public class AnnotatedString internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val text: StringBuilder = StringBuilder(capacity)
|
||||
private val spanStyles: MutableList<MutableRange<SpanStyle>> = mutableListOf()
|
||||
private val styleStack: MutableList<MutableRange<out Any>> = mutableListOf()
|
||||
private val text = StringBuilder(capacity)
|
||||
private val spanStyles = ArrayList<MutableRange<SpanStyle>>()
|
||||
private val styleStack = ArrayList<MutableRange<out Any>>()
|
||||
|
||||
/**
|
||||
* Create an [Builder] instance using the given [String].
|
||||
|
||||
Reference in New Issue
Block a user