Skip to content

Commit

Permalink
Add custom generic font mapping until JetBrains/compose-multiplatform…
Browse files Browse the repository at this point in the history
…-core#994 is (hopefully) merged
  • Loading branch information
zacharee committed Jan 16, 2024
1 parent c219292 commit 9cc1f02
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package tk.zwander.commonCompose.util

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalFontFamilyResolver
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.GenericFontFamily
import korlibs.memory.Platform
import tk.zwander.common.util.CrossPlatformBugsnag

object FontMapper {
private val GenericFontFamiliesMapping: Map<String, List<String>> by lazy {
when {
Platform.isLinux ->
mapOf(
FontFamily.SansSerif.name to listOf("Noto Sans", "DejaVu Sans", "Arial"),
FontFamily.Serif.name to listOf("Noto Serif", "DejaVu Serif", "Times New Roman"),
FontFamily.Monospace.name to listOf("Noto Sans Mono", "DejaVu Sans Mono", "Consolas"),
// better alternative?
FontFamily.Cursive.name to listOf("Comic Sans MS"),
)
Platform.isWindows ->
mapOf(
// Segoe UI is the Windows system font, so try it first.
// See https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts
FontFamily.SansSerif.name to listOf("Segoe UI", "Arial"),
FontFamily.Serif.name to listOf("Times New Roman"),
FontFamily.Monospace.name to listOf("Consolas"),
FontFamily.Cursive.name to listOf("Comic Sans MS"),
)
Platform.isMac || Platform.isIos || Platform.isTvos || Platform.isWatchos ->
mapOf(
// .AppleSystem* aliases is the only legal way to get default SF and NY fonts.
FontFamily.SansSerif.name to listOf(".AppleSystemUIFont", "Helvetica Neue", "Helvetica"),
FontFamily.Serif.name to listOf(".AppleSystemUIFontSerif", "Times", "Times New Roman"),
FontFamily.Monospace.name to listOf(".AppleSystemUIFontMonospaced", "Menlo", "Courier"),
// Safari "font-family: cursive" real font names from macOS and iOS.
FontFamily.Cursive.name to listOf("Apple Chancery", "Snell Roundhand"),
)
Platform.isAndroid -> // https://m3.material.io/styles/typography/fonts
mapOf(
FontFamily.SansSerif.name to listOf("Roboto", "Noto Sans"),
FontFamily.Serif.name to listOf("Roboto Serif", "Noto Serif"),
FontFamily.Monospace.name to listOf("Roboto Mono", "Noto Sans Mono"),
FontFamily.Cursive.name to listOf("Comic Sans MS"),
)
else ->
mapOf(
FontFamily.SansSerif.name to listOf("Arial"),
FontFamily.Serif.name to listOf("Times New Roman"),
FontFamily.Monospace.name to listOf("Consolas"),
FontFamily.Cursive.name to listOf("Comic Sans MS"),
)
}
}

@OptIn(ExperimentalTextApi::class)
@Composable
fun mapGenericFontFamilyToSpecificFontFamily(family: FontFamily): FontFamily {
if (family !is GenericFontFamily) {
return family
}

val mapped = GenericFontFamiliesMapping[family.name] ?: return family
val resolver = LocalFontFamilyResolver.current

return mapped.firstNotNullOfOrNull { fontName ->
try {
FontFamily(fontName).also {
resolver.resolve()
}
} catch (e: Throwable) {
CrossPlatformBugsnag.notify(Exception("Unable to load font $fontName.", e))
null
}
} ?: family
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package tk.zwander.commonCompose.view.components

import androidx.compose.material3.ColorScheme
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SwitchColors
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.graphics.Color
import tk.zwander.commonCompose.util.FontMapper
import tk.zwander.commonCompose.util.ThemeInfo
import tk.zwander.commonCompose.util.getThemeInfo

/**
* A Material theme with custom colors and such.
*/
@Composable
fun CustomMaterialTheme(block: @Composable()() -> Unit) {
fun CustomMaterialTheme(block: @Composable () -> Unit) {
val themeInfo = getThemeInfo()

val colorScheme = if (themeInfo.isDarkMode) {
Expand All @@ -26,7 +28,15 @@ fun CustomMaterialTheme(block: @Composable()() -> Unit) {
MaterialTheme(
colorScheme = colorScheme,
) {
block()
CompositionLocalProvider(
LocalTextStyle provides LocalTextStyle.current.copy(
fontFamily = LocalTextStyle.current.fontFamily?.let {
FontMapper.mapGenericFontFamilyToSpecificFontFamily(it)
},
),
) {
block()
}
}
}

Expand Down

0 comments on commit 9cc1f02

Please sign in to comment.