From bb6b4c208de54c8cba60d8d44dade2c7e2974b36 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 13 Mar 2023 17:38:30 -0400 Subject: [PATCH] Moves SVG generation to fetcher (IO) and avoids the use of TrimIndent, which is too slow (2-10ms each) for this context. --- .../amethyst/ui/components/Robohash.kt | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/Robohash.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/Robohash.kt index 28def69869..2aa9f57c51 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/Robohash.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/Robohash.kt @@ -1,11 +1,20 @@ package com.vitorpamplona.amethyst.ui.components import android.content.Context +import android.net.Uri import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb +import coil.ImageLoader +import coil.decode.DataSource +import coil.decode.ImageSource +import coil.fetch.Fetcher +import coil.fetch.SourceResult import coil.request.ImageRequest -import java.nio.ByteBuffer +import coil.request.Options +import okio.Buffer import java.security.MessageDigest +import kotlin.time.ExperimentalTime +import kotlin.time.measureTimedValue private fun toHex(color: Color): String { val argb = color.toArgb() @@ -40,29 +49,54 @@ private fun svgString(msg: String): String { val mouth = mouths[mouthIndex] val accessory = accessories[accIndex] - return """ - - - - - Robohash $hashHex - ${background}${body.paths}${face.paths}${eye.paths}${mouth.paths}${accessory.paths} - - """.trimIndent() + return """ + + + + Robohash $hashHex + ${background}${body.paths}${face.paths}${eye.paths}${mouth.paths}${accessory.paths} +""" } +class HashImageFetcher( + private val context: Context, + private val data: Uri +) : Fetcher { + + @OptIn(ExperimentalTime::class) + override suspend fun fetch(): SourceResult { + val (value, elapsed) = measureTimedValue { + val source = try { + Buffer().apply { write(svgString(data.toString()).toByteArray()) } + } finally { + } + + SourceResult( + source = ImageSource(source, context), + mimeType = null, + dataSource = DataSource.MEMORY + ) + } + println("Elapsed: $elapsed") + + return value + } + + class Factory : Fetcher.Factory { + override fun create(data: Uri, options: Options, imageLoader: ImageLoader): Fetcher { + return HashImageFetcher(options.context, data) + } + } +} object Robohash { fun imageRequest(context: Context, message: String): ImageRequest { return ImageRequest .Builder(context) - .data( - ByteBuffer.wrap( - svgString(message).toByteArray() - ) - ) + .data("robohash:$message") + .fetcherFactory(HashImageFetcher.Factory()) .crossfade(100) .build() }