Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for creating System fonts #769

Merged
merged 3 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
package com.splendo.kaluga.example.shared.stylable

import com.splendo.kaluga.resources.DefaultColors
import com.splendo.kaluga.resources.FontStyle
import com.splendo.kaluga.resources.FontTrait
import com.splendo.kaluga.resources.FontWeight
import com.splendo.kaluga.resources.createDefaultFont
import com.splendo.kaluga.resources.defaultBoldFont
import com.splendo.kaluga.resources.defaultFont
import com.splendo.kaluga.resources.defaultItalicFont
Expand All @@ -42,6 +46,18 @@ object TextStyles {
val defaultMonospaceText by lazy {
KalugaTextStyle(defaultMonospaceFont, DefaultColors.dimGray, 12.0f)
}
val semiBoldText by lazy {
KalugaTextStyle(createDefaultFont(FontWeight.SEMI_BOLD), DefaultColors.dimGray, 12.0f)
}
val serifText by lazy {
KalugaTextStyle(createDefaultFont(FontWeight.NORMAL, FontStyle.SERIF), DefaultColors.dimGray, 12.0f)
}
val italicBoldText by lazy {
KalugaTextStyle(createDefaultFont(FontWeight.BOLD, traits = setOf(FontTrait.ITALIC)), DefaultColors.dimGray, 12.0f)
}
val lightItalicMonospaceText by lazy {
KalugaTextStyle(createDefaultFont(FontWeight.LIGHT, FontStyle.MONOSPACE, traits = setOf(FontTrait.ITALIC)), DefaultColors.dimGray, 12.0f)
}
val whiteText by lazy {
KalugaTextStyle(defaultFont, DefaultColors.white, 12.0f)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ class LabelViewModel(styledStringBuilderProvider: StyledStringBuilder.Provider)
KalugaLabel.Plain("Bold Text", TextStyles.defaultBoldText),
KalugaLabel.Plain("Italic Text", TextStyles.defaultItalicText),
KalugaLabel.Plain("Monospace Text", TextStyles.defaultMonospaceText),
KalugaLabel.Plain("SemiBold Text", TextStyles.semiBoldText),
KalugaLabel.Plain("Serif Text", TextStyles.serifText),
KalugaLabel.Plain("Italic Bold Text", TextStyles.italicBoldText),
KalugaLabel.Plain("Light Italic Monospace Text", TextStyles.lightItalicMonospaceText),
KalugaLabel.Plain("Red Text", TextStyles.redText),
KalugaLabel.Plain("Opposite Aligned Text", TextStyles.oppositeText),
KalugaLabel.Styled(
Expand Down
39 changes: 39 additions & 0 deletions resources/api/androidLib/resources.api
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
public final class com/splendo/kaluga/resources/AndroidFont {
public static final fun createDefaultFont (ILcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;)Landroid/graphics/Typeface;
public static synthetic fun createDefaultFont$default (ILcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;ILjava/lang/Object;)Landroid/graphics/Typeface;
public static final fun getDefaultBoldFont ()Landroid/graphics/Typeface;
public static final fun getDefaultFont ()Landroid/graphics/Typeface;
public static final fun getDefaultItalicFont ()Landroid/graphics/Typeface;
Expand Down Expand Up @@ -396,6 +398,38 @@ public abstract interface class com/splendo/kaluga/resources/FontLoader {
public abstract fun loadFont (Ljava/lang/String;Landroid/graphics/Typeface;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class com/splendo/kaluga/resources/FontStyle : java/lang/Enum {
public static final field DEFAULT Lcom/splendo/kaluga/resources/FontStyle;
public static final field MONOSPACE Lcom/splendo/kaluga/resources/FontStyle;
public static final field SERIF Lcom/splendo/kaluga/resources/FontStyle;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/splendo/kaluga/resources/FontStyle;
public static fun values ()[Lcom/splendo/kaluga/resources/FontStyle;
}

public final class com/splendo/kaluga/resources/FontTrait : java/lang/Enum {
public static final field ITALIC Lcom/splendo/kaluga/resources/FontTrait;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/splendo/kaluga/resources/FontTrait;
public static fun values ()[Lcom/splendo/kaluga/resources/FontTrait;
}

public final class com/splendo/kaluga/resources/FontWeight : java/lang/Enum {
public static final field BLACK Lcom/splendo/kaluga/resources/FontWeight;
public static final field BOLD Lcom/splendo/kaluga/resources/FontWeight;
public static final field EXTRA_BOLD Lcom/splendo/kaluga/resources/FontWeight;
public static final field EXTRA_LIGHT Lcom/splendo/kaluga/resources/FontWeight;
public static final field LIGHT Lcom/splendo/kaluga/resources/FontWeight;
public static final field MEDIUM Lcom/splendo/kaluga/resources/FontWeight;
public static final field NORMAL Lcom/splendo/kaluga/resources/FontWeight;
public static final field SEMI_BOLD Lcom/splendo/kaluga/resources/FontWeight;
public static final field THIN Lcom/splendo/kaluga/resources/FontWeight;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun getValue ()I
public static fun valueOf (Ljava/lang/String;)Lcom/splendo/kaluga/resources/FontWeight;
public static fun values ()[Lcom/splendo/kaluga/resources/FontWeight;
}

public final class com/splendo/kaluga/resources/HSLColor {
public static final field Companion Lcom/splendo/kaluga/resources/HSLColor$Companion;
public fun <init> (DDDD)V
Expand Down Expand Up @@ -445,6 +479,11 @@ public abstract interface class com/splendo/kaluga/resources/KalugaColorLoader {
public abstract fun loadColor (Ljava/lang/String;Ljava/lang/Integer;)Ljava/lang/Integer;
}

public final class com/splendo/kaluga/resources/KalugaFontKt {
public static final fun createDefaultFont (Lcom/splendo/kaluga/resources/FontWeight;Lcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;)Landroid/graphics/Typeface;
public static synthetic fun createDefaultFont$default (Lcom/splendo/kaluga/resources/FontWeight;Lcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;ILjava/lang/Object;)Landroid/graphics/Typeface;
}

public final class com/splendo/kaluga/resources/KalugaImage {
public fun <init> (Landroid/graphics/drawable/Drawable;)V
public final fun component1 ()Landroid/graphics/drawable/Drawable;
Expand Down
39 changes: 39 additions & 0 deletions resources/api/jvm/resources.api
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,38 @@ public abstract interface class com/splendo/kaluga/resources/FontLoader {
public abstract fun loadFont (Ljava/lang/String;Lcom/splendo/kaluga/resources/KalugaFont;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class com/splendo/kaluga/resources/FontStyle : java/lang/Enum {
public static final field DEFAULT Lcom/splendo/kaluga/resources/FontStyle;
public static final field MONOSPACE Lcom/splendo/kaluga/resources/FontStyle;
public static final field SERIF Lcom/splendo/kaluga/resources/FontStyle;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/splendo/kaluga/resources/FontStyle;
public static fun values ()[Lcom/splendo/kaluga/resources/FontStyle;
}

public final class com/splendo/kaluga/resources/FontTrait : java/lang/Enum {
public static final field ITALIC Lcom/splendo/kaluga/resources/FontTrait;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/splendo/kaluga/resources/FontTrait;
public static fun values ()[Lcom/splendo/kaluga/resources/FontTrait;
}

public final class com/splendo/kaluga/resources/FontWeight : java/lang/Enum {
public static final field BLACK Lcom/splendo/kaluga/resources/FontWeight;
public static final field BOLD Lcom/splendo/kaluga/resources/FontWeight;
public static final field EXTRA_BOLD Lcom/splendo/kaluga/resources/FontWeight;
public static final field EXTRA_LIGHT Lcom/splendo/kaluga/resources/FontWeight;
public static final field LIGHT Lcom/splendo/kaluga/resources/FontWeight;
public static final field MEDIUM Lcom/splendo/kaluga/resources/FontWeight;
public static final field NORMAL Lcom/splendo/kaluga/resources/FontWeight;
public static final field SEMI_BOLD Lcom/splendo/kaluga/resources/FontWeight;
public static final field THIN Lcom/splendo/kaluga/resources/FontWeight;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun getValue ()I
public static fun valueOf (Ljava/lang/String;)Lcom/splendo/kaluga/resources/FontWeight;
public static fun values ()[Lcom/splendo/kaluga/resources/FontWeight;
}

public final class com/splendo/kaluga/resources/HSLColor {
public static final field Companion Lcom/splendo/kaluga/resources/HSLColor$Companion;
public fun <init> (DDDD)V
Expand Down Expand Up @@ -420,6 +452,8 @@ public abstract interface class com/splendo/kaluga/resources/ImageLoader {
}

public final class com/splendo/kaluga/resources/JvmFont {
public static final fun createDefaultFont (ILcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;)Lcom/splendo/kaluga/resources/KalugaFont;
public static synthetic fun createDefaultFont$default (ILcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;ILjava/lang/Object;)Lcom/splendo/kaluga/resources/KalugaFont;
public static final fun getDefaultBoldFont ()Lcom/splendo/kaluga/resources/KalugaFont;
public static final fun getDefaultFont ()Lcom/splendo/kaluga/resources/KalugaFont;
public static final fun getDefaultItalicFont ()Lcom/splendo/kaluga/resources/KalugaFont;
Expand Down Expand Up @@ -449,6 +483,11 @@ public final class com/splendo/kaluga/resources/KalugaFont {
public fun <init> ()V
}

public final class com/splendo/kaluga/resources/KalugaFontKt {
public static final fun createDefaultFont (Lcom/splendo/kaluga/resources/FontWeight;Lcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;)Lcom/splendo/kaluga/resources/KalugaFont;
public static synthetic fun createDefaultFont$default (Lcom/splendo/kaluga/resources/FontWeight;Lcom/splendo/kaluga/resources/FontStyle;Ljava/util/Set;ILjava/lang/Object;)Lcom/splendo/kaluga/resources/KalugaFont;
}

public final class com/splendo/kaluga/resources/KalugaImage {
public fun <init> ()V
}
Expand Down
32 changes: 32 additions & 0 deletions resources/src/androidLibMain/kotlin/KalugaFont.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package com.splendo.kaluga.resources

import android.graphics.Typeface
import android.os.Build

/**
* Class describing a font
Expand All @@ -45,3 +46,34 @@ actual val defaultItalicFont: KalugaFont get() = Typeface.create(Typeface.DEFAUL
* The default monospace system [KalugaFont]
*/
actual val defaultMonospaceFont: KalugaFont get() = Typeface.MONOSPACE

/**
* Creates a system font with a given weight, [FontStyle] and [FontTrait]
* @param weight the weight to apply. Must be in range [1, 100]
* @param style the [FontStyle] to apply
* @param traits the set of [FontTrait] to apply
* @return a [KalugaFont] representing the system font with the given specifications
*/
actual fun createDefaultFont(weight: Int, style: FontStyle, traits: Set<FontTrait>): KalugaFont {
val typeface = when (style) {
FontStyle.DEFAULT -> Typeface.DEFAULT
FontStyle.SERIF -> Typeface.SERIF
FontStyle.MONOSPACE -> Typeface.MONOSPACE
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Typeface.create(typeface, weight, FontTrait.ITALIC in traits)
} else {
val typefaceStyle = traits.fold(
if (weight >= FontWeight.SEMI_BOLD.value) {
Typeface.BOLD
} else {
Typeface.NORMAL
},
) { acc, trait ->
acc or when (trait) {
FontTrait.ITALIC -> Typeface.ITALIC
}
}
Typeface.create(typeface, typefaceStyle)
}
}
66 changes: 66 additions & 0 deletions resources/src/commonMain/kotlin/KalugaFont.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,69 @@ expect val defaultItalicFont: KalugaFont
* The default monospace system [KalugaFont]
*/
expect val defaultMonospaceFont: KalugaFont

/**
* Style of the system font
*/
enum class FontStyle {

/**
* Default system font style
*/
DEFAULT,

/**
* Serif system font style
*/
SERIF,

/**
* Monospace system font style
*/
MONOSPACE,
}

/**
* Trait to add to a system font
*/
enum class FontTrait {

/**
* Makes the system font appear in italics
*/
ITALIC,
}

/**
* Font weights as defined by [W3](https://www.w3.org/TR/css-fonts-4/#font-weight-prop)
* @property value the value of the weight. Must be in range [1, 100]
*/
enum class FontWeight(val value: Int) {
THIN(100),
EXTRA_LIGHT(200),
LIGHT(300),
NORMAL(400),
MEDIUM(500),
SEMI_BOLD(600),
BOLD(700),
EXTRA_BOLD(800),
BLACK(900),
}

/**
* Creates a system font with a given [FontWeight], [FontStyle] and [FontTrait]
* @param weight the [FontWeight] to apply
* @param style the [FontStyle] to apply
* @param traits the set of [FontTrait] to apply
* @return a [KalugaFont] representing the system font with the given specifications
*/
fun createDefaultFont(weight: FontWeight, style: FontStyle = FontStyle.DEFAULT, traits: Set<FontTrait> = emptySet()): KalugaFont = createDefaultFont(weight.value, style, traits)

/**
* Creates a system font with a given weight, [FontStyle] and [FontTrait]
* @param weight the weight to apply. Must be in range [1, 100]
* @param style the [FontStyle] to apply
* @param traits the set of [FontTrait] to apply
* @return a [KalugaFont] representing the system font with the given specifications
*/
expect fun createDefaultFont(weight: Int, style: FontStyle = FontStyle.DEFAULT, traits: Set<FontTrait> = emptySet()): KalugaFont
79 changes: 79 additions & 0 deletions resources/src/iosMain/kotlin/KalugaFont.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,19 @@
package com.splendo.kaluga.resources

import platform.UIKit.UIFont
import platform.UIKit.UIFontDescriptorSystemDesignDefault
import platform.UIKit.UIFontDescriptorSystemDesignMonospaced
import platform.UIKit.UIFontDescriptorSystemDesignSerif
import platform.UIKit.UIFontDescriptorTraitItalic
import platform.UIKit.UIFontWeightBlack
import platform.UIKit.UIFontWeightBold
import platform.UIKit.UIFontWeightHeavy
import platform.UIKit.UIFontWeightLight
import platform.UIKit.UIFontWeightMedium
import platform.UIKit.UIFontWeightRegular
import platform.UIKit.UIFontWeightSemibold
import platform.UIKit.UIFontWeightThin
import platform.UIKit.UIFontWeightUltraLight
import platform.UIKit.labelFontSize

/**
Expand All @@ -45,3 +57,70 @@ actual val defaultItalicFont: KalugaFont get() = UIFont.italicSystemFontOfSize(U
* The default monospace system [KalugaFont]
*/
actual val defaultMonospaceFont: KalugaFont get() = UIFont.monospacedSystemFontOfSize(UIFont.labelFontSize, UIFontWeightRegular)

/**
* Creates a system font with a given weight, [FontStyle] and [FontTrait]
* @param weight the weight to apply. Must be in range [1, 100]
* @param style the [FontStyle] to apply
* @param traits the set of [FontTrait] to apply
* @return a [KalugaFont] representing the system font with the given specifications
*/
actual fun createDefaultFont(weight: Int, style: FontStyle, traits: Set<FontTrait>): KalugaFont {
val calculateWeight: (Double, Double, FontWeight) -> Double = { uiFontWeight, factor, fontWeight ->
val difference = factor * ((fontWeight.value - weight).toDouble() / 100.0)
uiFontWeight - difference
}
// UIFontWeight is rather weird in that it is not evenly distributed.
// For instance, UIFontWeightRegular is 0.0, UIFontWeightMedium is 0.23000000417232513, and UIFontWeightLight is -0.4000000059604645
// To account for these inconsistencies, we interpolate between the steps
val actualWeight = when {
weight <= FontWeight.THIN.value -> {
// Not a bug, iOS flips these names
calculateWeight(UIFontWeightUltraLight, UIFontWeightThin - UIFontWeightUltraLight, FontWeight.THIN)
}
weight <= FontWeight.EXTRA_LIGHT.value -> {
calculateWeight(UIFontWeightThin, UIFontWeightThin - UIFontWeightUltraLight, FontWeight.EXTRA_LIGHT)
}
weight <= FontWeight.LIGHT.value -> {
calculateWeight(UIFontWeightLight, UIFontWeightLight - UIFontWeightThin, FontWeight.LIGHT)
}
weight <= FontWeight.NORMAL.value -> {
calculateWeight(UIFontWeightRegular, UIFontWeightRegular - UIFontWeightLight, FontWeight.NORMAL)
}
weight <= FontWeight.MEDIUM.value -> {
calculateWeight(UIFontWeightMedium, UIFontWeightMedium - UIFontWeightRegular, FontWeight.MEDIUM)
}
weight <= FontWeight.SEMI_BOLD.value -> {
calculateWeight(UIFontWeightSemibold, UIFontWeightSemibold - UIFontWeightMedium, FontWeight.SEMI_BOLD)
}
weight <= FontWeight.BOLD.value -> {
calculateWeight(UIFontWeightBold, UIFontWeightBold - UIFontWeightSemibold, FontWeight.BOLD)
}
weight <= FontWeight.EXTRA_BOLD.value -> {
calculateWeight(UIFontWeightHeavy, UIFontWeightHeavy - UIFontWeightBold, FontWeight.EXTRA_BOLD)
}
weight <= FontWeight.EXTRA_LIGHT.value -> {
calculateWeight(UIFontWeightBlack, UIFontWeightBlack - UIFontWeightHeavy, FontWeight.BLACK)
}
else -> {
val difference = ((weight - FontWeight.BLACK.value).toDouble() / 100.0) * UIFontWeightBlack - UIFontWeightHeavy
UIFontWeightBlack + difference
}
}
val font = UIFont.systemFontOfSize(UIFont.labelFontSize, actualWeight)
val design = when (style) {
FontStyle.DEFAULT -> UIFontDescriptorSystemDesignDefault
FontStyle.SERIF -> UIFontDescriptorSystemDesignSerif
FontStyle.MONOSPACE -> UIFontDescriptorSystemDesignMonospaced
}
val symbolicTraits = traits.fold(0U) { acc, trait ->
when (trait) {
FontTrait.ITALIC -> acc or UIFontDescriptorTraitItalic
}
}
return UIFont.fontWithDescriptor(
font.fontDescriptor.fontDescriptorWithDesign(design)!!
.fontDescriptorWithSymbolicTraits(symbolicTraits)!!,
UIFont.labelFontSize,
)
}
9 changes: 9 additions & 0 deletions resources/src/jsMain/kotlin/KalugaFont.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,12 @@ actual val defaultItalicFont: KalugaFont get() = KalugaFont()
* The default monospace system [KalugaFont]
*/
actual val defaultMonospaceFont: KalugaFont get() = KalugaFont()

/**
* Creates a system font with a given weight, [FontStyle] and [FontTrait]
* @param weight the weight to apply. Must be in range [1, 100]
* @param style the [FontStyle] to apply
* @param traits the set of [FontTrait] to apply
* @return a [KalugaFont] representing the system font with the given specifications
*/
actual fun createDefaultFont(weight: Int, style: FontStyle, traits: Set<FontTrait>): KalugaFont = KalugaFont()
9 changes: 9 additions & 0 deletions resources/src/jvmMain/kotlin/KalugaFont.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,12 @@ actual val defaultItalicFont: KalugaFont get() = KalugaFont()
* The default monospace system [KalugaFont]
*/
actual val defaultMonospaceFont: KalugaFont get() = KalugaFont()

/**
* Creates a system font with a given weight, [FontStyle] and [FontTrait]
* @param weight the weight to apply. Must be in range [1, 100]
* @param style the [FontStyle] to apply
* @param traits the set of [FontTrait] to apply
* @return a [KalugaFont] representing the system font with the given specifications
*/
actual fun createDefaultFont(weight: Int, style: FontStyle, traits: Set<FontTrait>): KalugaFont = KalugaFont()
Loading