still trying to find out how to set the default fo...
# compose-desktop
z
still trying to find out how to set the default font in compose desktop (on linux)? which font is used if i just do Text("ipsum") ? and where is this set? can i change it?
k
take a look on the resources library. it provides a way to use custom fonts as well https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-images-resources.html
z
thats not what i mean. i know that. i want to know what font ist used when i do not set anything
i
Compose uses system font based on OS+FontFamly here
can i change it?
I guess you're looking for a way to set in implicitly instead of writing the parameter for each element. It's done in component libraries like material(3) via composition locals. See
LocalTextStyle
z
my problem is that if i set a font via FontFamily then i can only set 1 font. but no second fallback font. and thats important because damn emojis dont work properly on linux. and google seems to lazy to make a Noto font with text AND color emoji. so now i set a font with only coloremoji in fontfamily and when text is displayed it paints emojis from the font i specify and normal text from the default font. but the default font is not Noto and looks no so nice
FontFamily.SansSerif.name to listOf("Noto Sans", "DejaVu Sans", "Arial"), aaaaaaaahh. holy cow. is that it? can i do this in my app to set more than 1 font? and will it respect the order? because thats what i been looking for for days now
now i do something like this: DefaultFont = FontFamily( Font(resource = "fonts/Noto-COLRv1-COLRv1_normal_chars_removed.ttf", FontWeight.Normal, FontStyle.Normal), Font(resource = "fonts/Noto-COLRv1-COLRv1_normal_chars_removed.ttf", FontWeight.SemiBold, FontStyle.Normal), Font(resource = "fonts/Noto-COLRv1-COLRv1_normal_chars_removed.ttf", FontWeight.Bold, FontStyle.Normal), Font(resource = "fonts/NotoSans-Regular.ttf", FontWeight.Normal, FontStyle.Normal), Font(resource = "fonts/NotoSans-SemiBold.ttf", FontWeight.SemiBold, FontStyle.Normal), Font(resource = "fonts/NotoSans-SemiBold.ttf", FontWeight.Bold, FontStyle.Normal), )
@Ivan Matkov i don't know how to set the os default font im my app. any ideas?
i
Defaults are not configurable. Use composition locals like
LocalTextStyle
as I wrote above
z
but will that work like i need? FontFamily will be used first and only when that font does not have the needed charcters it will fallback to LocalTextStyle ?
i
I guess no - afaik it doesn't work on individual chars level. fallback happens only if font cannot be loaded
z
image.png
is there a solution. you can see the problem in the image
in the textfield of the message. text and emoji are mixed. as is normal in chat messages
now since i need 2 font files, now i can display emojis correct, but the rest of the text will not use the noto TTF font. but some other font from the OS. but i want to have noto for text
if i use just 1 font file. then either the emoji show tofu or the the text is broken
i
You can use
buildAnnotatedString
for applying different style to part of the text, but it will require some rules and knowing in advance what requires displaying with what
z
yeah thats too aweful and super slow aswell
🙁 1
i
z
but there is now way to specify 2 TTF file which are tried by linux fontconfig in order?
DefaultFont = FontFamily( Font(resource = "fonts/Noto-COLRv1-COLRv1_normal_chars_removed.ttf", FontWeight.Normal, FontStyle.Normal), Font(resource = "fonts/Noto-COLRv1-COLRv1_normal_chars_removed.ttf", FontWeight.SemiBold, FontStyle.Normal), Font(resource = "fonts/Noto-COLRv1-COLRv1_normal_chars_removed.ttf", FontWeight.Bold, FontStyle.Normal), Font(resource = "fonts/NotoSans-Regular.ttf", FontWeight.Normal, FontStyle.Normal), Font(resource = "fonts/NotoSans-SemiBold.ttf", FontWeight.SemiBold, FontStyle.Normal), Font(resource = "fonts/NotoSans-SemiBold.ttf", FontWeight.Bold, FontStyle.Normal), )
i can specify them like this. but the second fonts in the list are ignored sadly
i
It's not about simultaneously using both
jfyi @Oleksandr Karpovich [JB] made some progress on implementing this - https://github.com/JetBrains/skiko/pull/935 The main reason was WASM, but it's shared code, so linux might have benefit from this too
t
I have been poking around in the internal code to see what I could use publicly, and the best I have come up with so far...
Copy code
import androidx.compose.ui.text.font.createFontFamilyResolver
import androidx.compose.ui.text.platform.FontLoadResult

@OptIn(ExperimentalStdlibApi::class)
fun main() {
    val codePoint = 0x23FE
    println("Code point: 0x${codePoint.toHexString(HexFormat.UpperCase)}")

    // In @Composable code you would use:
    // val fontFamilyResolver = LocalFontFamilyResolver.current
    val fontFamilyResolver = createFontFamilyResolver()
    println("Font family resolver is: $fontFamilyResolver")

    val fontFamiliesToTry = sequenceOf(NotoSans, NotoSansSymbols, NotoSansSymbols2, LastResort)

    fontFamiliesToTry.forEach { fontFamily ->
        println("Trying font family: $fontFamily")
        val something = fontFamilyResolver.resolve(fontFamily).value
        if (something is FontLoadResult) {
            val skiaTypeface: org.jetbrains.skia.Typeface = checkNotNull(something.typeface)
            println("  Resolved to typeface: $skiaTypeface")
            val glyph = skiaTypeface.getUTF32Glyph(codePoint)
            if (glyph == 0.toShort()) {
                println("  Did not find glyph")
            } else {
                println("  Found glyph: $glyph")
            }
        }
    }
}
there's no guarantee that the
something
will be
FontLoadResult
, but certainly on the current version, if the family is a
FontListFontFamily
, you get that type always, so I guess the code works until they change the internal code in the future