Viewing is open to everyone. Downloading and starring need a GitHub sign-in. Sign in with GitHub

CKeyImage.kt

v0.1.0-build.85 Latest Commit ede38f5

Size
3.1 KB
Lines
73
Language
kotlin
SHA-256
531373186896…
View on GitHub

Sign in with GitHub to download. Each download is recorded with your GitHub username.

1package org.openckey.ckey.compose
2
3import androidx.compose.foundation.Image
4import androidx.compose.foundation.layout.BoxWithConstraints
5import androidx.compose.foundation.layout.aspectRatio
6import androidx.compose.foundation.layout.defaultMinSize
7import androidx.compose.foundation.layout.fillMaxSize
8import androidx.compose.runtime.Composable
9import androidx.compose.runtime.LaunchedEffect
10import androidx.compose.runtime.getValue
11import androidx.compose.runtime.produceState
12import androidx.compose.runtime.rememberUpdatedState
13import androidx.compose.ui.Modifier
14import androidx.compose.ui.graphics.ImageBitmap
15import androidx.compose.ui.graphics.asImageBitmap
16import androidx.compose.ui.layout.ContentScale
17import androidx.compose.ui.platform.LocalContext
18import androidx.compose.ui.platform.LocalDensity
19import androidx.compose.ui.unit.Constraints
20import androidx.compose.ui.unit.dp
21import kotlinx.coroutines.Dispatchers
22import kotlinx.coroutines.withContext
23import org.openckey.ckey.CKey
24import org.openckey.ckey.CKeyStyle
25import org.openckey.ckey.CKeySymbol
26import org.openckey.ckey.EccLevel
27import org.openckey.ckey.Layout
28import org.openckey.ckey.RasterPolicy
29
30/**
31 * Shows a CKey for [data]. Square; rendered off the main thread as native
32 * pixels at the exact pixel size laid out (no SVG, file or WebView), and
33 * re-rendered when the size or any parameter changes.
34 *
35 * With [transparent] = true unpainted pixels are transparent and the
36 * composable shows whatever is behind it: make sure that background has
37 * enough contrast (see CKeySymbol.certify).
38 *
39 * Encoding or style failures (payload too large, style refused under
40 * StylePolicy.STRICT) leave the composable empty and are passed to [onError].
41 */
42@Composable
43fun CKeyImage(
44 data: String,
45 modifier: Modifier = Modifier,
46 style: CKeyStyle? = null,
47 level: EccLevel = EccLevel.M,
48 layout: Layout = Layout.STANDARD,
49 policy: RasterPolicy = RasterPolicy.COVERAGE,
50 transparent: Boolean = false,
51 contentDescription: String? = "CKey",
52 onError: ((Throwable) -> Unit)? = null,
53) {
54 val context = LocalContext.current
55 LaunchedEffect(Unit) { CKey.install(context) }
56 val currentOnError by rememberUpdatedState(onError)
57 BoxWithConstraints(modifier.defaultMinSize(192.dp, 192.dp).aspectRatio(1f)) {
58 val fallback = with(LocalDensity.current) { 192.dp.roundToPx() }
59 val w = if (constraints.maxWidth == Constraints.Infinity) fallback else constraints.maxWidth
60 val h = if (constraints.maxHeight == Constraints.Infinity) fallback else constraints.maxHeight
61 val side = minOf(w, h).coerceIn(16, 4096)
62 val bitmap: ImageBitmap? by produceState<ImageBitmap?>(null, data, side, style, level, layout, policy, transparent) {
63 value = withContext(Dispatchers.Default) {
64 runCatching {
65 CKeySymbol.encode(data, 0, level, layout).toBitmap(side, policy, transparent, style).asImageBitmap()
66 }
67 }.onFailure { currentOnError?.invoke(it) }.getOrNull()
68 }
69 bitmap?.let {
70 Image(it, contentDescription, Modifier.fillMaxSize(), contentScale = ContentScale.Fit)
71 }
72 }
73}