Skip to content

Commit

Permalink
[wasm] demo: Load NotoSansSC alongside with NotoColorEmoji
Browse files Browse the repository at this point in the history
  • Loading branch information
Schahen committed Dec 13, 2024
1 parent 9627567 commit 550fe73
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,20 @@ import androidx.compose.ui.window.ComposeViewport
import androidx.navigation.ExperimentalBrowserHistoryApi
import androidx.navigation.compose.rememberNavController
import androidx.navigation.bindToNavigation
import kotlin.js.Promise
import kotlin.wasm.unsafe.UnsafeWasmMemoryApi
import kotlin.wasm.unsafe.withScopedMemoryAllocator
import kotlinx.browser.window
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.asDeferred
import kotlinx.coroutines.await
import kotlinx.coroutines.awaitAll
import org.khronos.webgl.ArrayBuffer
import org.khronos.webgl.Int8Array
import org.w3c.fetch.Response

private val notoColorEmoji = "./NotoColorEmoji.ttf"
private const val notoColorEmoji = "./NotoColorEmoji.ttf"
private const val notoSansSC = "./NotoSansSC-Regular.ttf"

@OptIn(ExperimentalComposeUiApi::class)
@ExperimentalBrowserHistoryApi
Expand All @@ -57,35 +62,40 @@ fun main() {
}

LaunchedEffect(Unit) {
val notoEmojisBytes = loadRes(notoColorEmoji).toByteArray()
val fontFamily = FontFamily(listOf(Font("NotoColorEmoji", notoEmojisBytes)))
fontFamilyResolver.preload(fontFamily)
val fontsDeferred = awaitAll(loadResAsync(notoColorEmoji), loadResAsync(notoSansSC)).zip(listOf(
"NotoColorEmoji",
"NotoSansSC"
))

fontsDeferred.forEach { (font, name) ->
val fontFamily = FontFamily(listOf(Font(name, font.toByteArray())))
fontFamilyResolver.preload(fontFamily)
}

fontsLoaded.value = true
}

}
}

@Composable
internal fun returnsNullable(): Any? = null
private suspend fun loadResAsync(url: String): Deferred<ArrayBuffer> {
return window.fetch(url).await<Response>().arrayBuffer().asDeferred()
}

suspend fun loadRes(url: String): ArrayBuffer {
return window.fetch(url).await<Response>().arrayBuffer().await()
return loadResAsync(url).await()
}

fun ArrayBuffer.toByteArray(): ByteArray {
val source = Int8Array(this, 0, byteLength)
return jsInt8ArrayToKotlinByteArray(source)
}

@JsFun(
""" (src, size, dstAddr) => {
const mem8 = new Int8Array(wasmExports.memory.buffer, dstAddr, size);
mem8.set(src);
}
"""
)
internal external fun jsExportInt8ArrayToWasm(src: Int8Array, size: Int, dstAddr: Int)
private fun wasmExportsMemoryBuffer(): ArrayBuffer = js("wasmExports.memory.buffer")
private fun jsExportInt8ArrayToWasm(destination: ArrayBuffer, src: Int8Array, size: Int, dstAddr: Int) {
val mem8 = Int8Array(destination, dstAddr, size)
mem8.set(src)
}

internal fun jsInt8ArrayToKotlinByteArray(x: Int8Array): ByteArray {
val size = x.length
Expand All @@ -94,7 +104,7 @@ internal fun jsInt8ArrayToKotlinByteArray(x: Int8Array): ByteArray {
return withScopedMemoryAllocator { allocator ->
val memBuffer = allocator.allocate(size)
val dstAddress = memBuffer.address.toInt()
jsExportInt8ArrayToWasm(x, size, dstAddress)
jsExportInt8ArrayToWasm(wasmExportsMemoryBuffer(), x, size, dstAddress)
ByteArray(size) { i -> (memBuffer + i).loadByte() }
}
}
Binary file not shown.

0 comments on commit 550fe73

Please sign in to comment.