hello again, has anyone figured out how to load fo...
# compose-web
hello again, has anyone figured out how to load fonts in compose/canvas?
Yes using webpack and loading fonts via require statements
I’m on my phone but there is a way
I made sure my font file was hosted somewhere. Then, I used the font-face CSS rule to name my font and set it to the target URL (https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face) Then, I created a CSS style which references the name of my font with a font family tag (https://www.w3schools.com/cssref/pr_font_font-family.asp). I'd paste code here but I'm using a custom framework so it wouldn't help too much. But you can use stylesheets (https://github.com/JetBrains/compose-jb/blob/master/tutorials/Web/Style_Dsl/README.md#stylesheet)
@David Herman correct me if i’m wrong, but this looks like it’s for the compose/dom approach not the compose/canvas approach
@agrosner any update on this? i found my own workaround, but i’m interested if there’s a more canonical way. thank you kindly
@jeran sorry yes, for the DOM.
sure ill send some code snippets
not sure if its the officially recommended way
caches the fonts using
Copy code
data class FontResourceImpl(private val font: AsyncFont, private val fileName: String) : FontResource {
    override val realFont: Font
        get() = fontOrHelp(fileName, font)
Copy code
interface FontResource {
    val realFont: Font

expect fun findFontResource(font: AsyncFont): FontResource?

data class AsyncFont(
    val identity: String,
    override val style: FontStyle,
    override val weight: FontWeight,
    val fontName: String
) : Font {
    override val loadingStrategy: FontLoadingStrategy = FontLoadingStrategy.Async
Copy code
fun FontStyleLocal.resolveFontFamily(): FontFamily {
    val fonts = **.fonts
    val font = when (this) {
        FontStyleLocal.BaseBold -> fonts.bold
        FontStyleLocal.BaseItalics -> fonts.italics
        FontStyleLocal.BaseRegular -> fonts.regular
        FontStyleLocal.Primary -> fonts.primary
    val found = findFontResource(font)?.realFont ?: Font(
        identity = "",
        data = ByteArray(0),
    return FontFamily(
composable to load font, we have our own design system so this just maps a token to the font and resource (probably dont need first portion of function)
add in
next to source a file I call it `01-resources.js`:
Copy code
    test: /\.(woff|woff2|eot|ttf|otf)$/i,
    loader: "file-loader"
this will instruct webpack to include font resource files and enable loading them from js / kt code using require
Copy code
implementation(npm("copy-webpack-plugin", "9.0.0"))
                implementation(npm("file-loader", "6.2.0"))
and fonts are included in
wow. thanks @agrosner! i’ve got another solution using window.fetch that i can post later. but gonna play around with this a bit first
np! cool
@agrosner - this was helpful, thanks! @jeran - did you ever get the
solution working? trying to decide best path forward so I was curious if there are alternate options to implement this
ah forgot about this! i actually didn’t get around to testing out andrew’s solution, so I didn’t post cause i wanted to do a comparison first. the code i have works fine and looks something like this:
Copy code
).then { response ->
}.then { arrayBuffer ->
    val byteLength = arrayBuffer.byteLength
    val byteArray = ByteArray(byteLength)
    val uInt8Array = Uint8Array(arrayBuffer)
    for (i in 0 until byteLength) {
        byteArray[i] = uInt8Array[i]
    return@then androidx.compose.ui.text.platform.Font(
        identity = url,
        data = byteArray,
        weight = weight,
        style = style,
where url is a url to a ttf, weight and style are corresponding
and you can use it something like this:
Copy code
fun rememberFont(
    url: String,
    weight: FontWeight,
    style: FontStyle,
): Font? {
    var font by remember { mutableStateOf<Font?>(null) }
    LaunchedEffect(path, weight, style) {
        font = loadFont(url, weight, style)
    return font
thank you for providing this information! I will try this out
@agrosner @Jeff T have either of you seen an issue with performance and custom fonts? i’ve been hunting down a performance issue in our little compose/canvas app, and from what i can tell rendering BasicText() composables can be slow if you use a custom font. it isn’t related to downloading the fonts, because that only happens once for us and we do that ahead of time anyway. and it also seems to be based on the number of composables. e.g. filling up the whole screen with lorem ipsum is fine if its a single text composable, but rendering 50 text composables with less text takes longer. also seems to be somewhat font dependent, seems like the Inter font takes longer than Aleo for example.
i wonder if it has to do with the size of the font 🤔. but the bytearray should already be in memory at this point…
https://github.com/JetBrains/androidx/pull/336 ok so, i actually think this was fixed 5 days ago lol. well, just a heads up then that this change is coming
thanks for this info! i still haven't incorporated my custom font yet, but I plan to do so in the coming days. I'll keep an eye out for this fix.