0

My final goal is to load fonts from a Variable Font Collection file. Most phones sold in China enable users to use custom fonts system-wide(ideally), but most of those fonts don't have full support for Unicode CJK ideographs, thus causing inconsistency, so I decided to embed Noto font into my app from the very beginning of development. I'm trying to utilize VFC to reduce the APK size.

In Compose there isn't a Font() function that takes a TTC index, so I tried defining a font family in XML file(which supports android:ttcIndex attribute), reading it as Typeface and finally turning it into a Compose FontFamily. I tried with a regular variable font at first, and when all that was done, I found that Text() didn't display text in the font weight I specified, instead falling back to FontWeight.Normal if present in font XML, or the font weight closest to that.

I put a regular variable font(Noto Sans CJK JP variable font) in /res/font directory, created a <font-name.xml> file, and the content is below:

<font-family xmlns:android="http://schemas.android.com/apk/res/android">
    <font android:font="@font/noto_sans_variable_jp"
        android:fontVariationSettings="'wght' 100"
        android:fontWeight="100"/>

    <!-- ... -->

    <font android:font="@font/noto_sans_variable_jp"
        android:fontVariationSettings="'wght' 900"
        android:fontWeight="900"/>
</font-family>

in the Activity, that XML font file is converted as Typeface:

val jp = resources.getFont(R.font.sans_jp)

and finally I set that Typeface as the fontFamily of my Text:

import androidx.compose.ui.text.font.FontFamily as ComposeFontFamily

Text(
    text = "測試文本",
    fontFamily = ComposeFontFamily(jp),
    fontWeight = FontWeight(900)
)

I expected the text to be displayed in the font weight I specified(900), but in the Preview the font weight fell back to 100(smallest weight in that file), code below:

@Preview
@Composable
private fun TypefacePreview() {
    MaterialTheme {
        Text(
            "測試文本",
            fontFamily = ComposeFontFamily(
                LocalContext.current.resources.getFont(R.font.sans_jp)
            ),
            fontWeight = FontWeight(900)
        )
    }
}

and in the app running on a physical device, the font weight 400.

By the way, when a Typeface has a fallback chain comprised of different fonts in the same font weight, there is no problem.

So [EDIT: even though I know such attempt is currently totally meaningless because that variable OTC file is ~30MB and loading it will cause OOM,] I wonder if there's something to do with how Compose treats Android Native Typeface internally.

EDIT: Some time ago I ended up implementing custom Font class and AndroidFont.TypefaceLoader object. Now the problem is that the Variable Font Collection is 30+MB for sans-serif and 50+MB for serif, causing my app to randomly crash in OOM.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.