mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 23:40:01 +07:00
Modding: allow mods to supply custom fonts (#8715)
* Modding: allow mods to supply custom fonts * Cleanup * Code cleanup --------- Co-authored-by: vegeta1k95 <vfylfhby>
This commit is contained in:
@ -19,7 +19,6 @@ import com.unciv.logic.files.UncivFiles
|
||||
import com.unciv.logic.event.EventBus
|
||||
import com.unciv.ui.screens.basescreen.UncivStage
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.components.Fonts
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.concurrency.Concurrency
|
||||
import java.io.File
|
||||
@ -41,7 +40,6 @@ open class AndroidLauncher : AndroidApplication() {
|
||||
}
|
||||
|
||||
val settings = UncivFiles.getSettingsForPlatformLaunchers(filesDir.path)
|
||||
val fontFamily = settings.fontFamily
|
||||
|
||||
// Manage orientation lock and display cutout
|
||||
val platformSpecificHelper = PlatformSpecificHelpersAndroid(this)
|
||||
@ -51,7 +49,7 @@ open class AndroidLauncher : AndroidApplication() {
|
||||
|
||||
val androidParameters = UncivGameParameters(
|
||||
crashReportSysInfo = CrashReportSysInfoAndroid,
|
||||
fontImplementation = NativeFontAndroid((Fonts.ORIGINAL_FONT_SIZE * settings.fontSizeMultiplier).toInt(), fontFamily),
|
||||
fontImplementation = FontAndroid(),
|
||||
customFileLocationHelper = customFileLocationHelper,
|
||||
platformSpecificHelper = platformSpecificHelper
|
||||
)
|
||||
|
112
android/src/com/unciv/app/NativeFontAndroid.kt → android/src/com/unciv/app/FontAndroid.kt
Executable file → Normal file
112
android/src/com/unciv/app/NativeFontAndroid.kt → android/src/com/unciv/app/FontAndroid.kt
Executable file → Normal file
@ -9,55 +9,95 @@ import android.graphics.fonts.FontFamily
|
||||
import android.graphics.fonts.FontStyle
|
||||
import android.graphics.fonts.SystemFonts
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.unciv.ui.components.FontFamilyData
|
||||
import com.unciv.ui.components.NativeFontImplementation
|
||||
import com.unciv.ui.components.FontImplementation
|
||||
import com.unciv.ui.components.Fonts
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* Created by tian on 2016/10/2.
|
||||
*/
|
||||
class NativeFontAndroid(
|
||||
private val size: Int,
|
||||
private val fontFamily: String
|
||||
) : NativeFontImplementation {
|
||||
private val fontList by lazy{
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) emptySet()
|
||||
else SystemFonts.getAvailableFonts()
|
||||
class FontAndroid : FontImplementation {
|
||||
|
||||
private val fontList: HashSet<Font> = hashSetOf()
|
||||
private val paint: Paint = Paint()
|
||||
private var currentFontFamily: String? = null
|
||||
|
||||
init {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
fontList.addAll(SystemFonts.getAvailableFonts())
|
||||
paint.isAntiAlias = true
|
||||
paint.strokeWidth = 0f
|
||||
paint.setARGB(255, 255, 255, 255)
|
||||
|
||||
}
|
||||
|
||||
private val paint by lazy{ createPaint() }
|
||||
fun createPaint() = Paint().apply {
|
||||
typeface = if (fontFamily.isNotBlank() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// Helper within the VERSION_CODES.Q gate: Evaluate a Font's desirability (lower = better) for a given family.
|
||||
fun Font.matchesFamily(family: String): Int {
|
||||
val name = file?.nameWithoutExtension ?: return Int.MAX_VALUE
|
||||
if (name == family) return 0
|
||||
if (!name.startsWith("$family-")) return Int.MAX_VALUE
|
||||
if (style.weight == FontStyle.FONT_WEIGHT_NORMAL && style.slant == FontStyle.FONT_SLANT_UPRIGHT) return 1
|
||||
return 2 +
|
||||
abs(style.weight - FontStyle.FONT_WEIGHT_NORMAL) / 100 +
|
||||
abs(style.slant - FontStyle.FONT_SLANT_UPRIGHT)
|
||||
override fun setFontFamily(fontFamilyData: FontFamilyData, size: Int) {
|
||||
paint.textSize = size.toFloat()
|
||||
|
||||
// Don't have to reload typeface if font-family didn't change
|
||||
if (currentFontFamily != fontFamilyData.invariantName) {
|
||||
currentFontFamily = fontFamilyData.invariantName
|
||||
|
||||
// Mod font
|
||||
if (fontFamilyData.filePath != null)
|
||||
{
|
||||
paint.typeface = createTypefaceCustom(fontFamilyData.filePath!!)
|
||||
}
|
||||
// System font
|
||||
else
|
||||
{
|
||||
paint.typeface = createTypefaceSystem(fontFamilyData.invariantName)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTypefaceSystem(name: String): Typeface {
|
||||
if (name.isNotBlank() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
{
|
||||
val font = fontList.mapNotNull {
|
||||
val distanceToRegular = it.matchesFamily(fontFamily)
|
||||
val distanceToRegular = it.matchesFamily(name)
|
||||
if (distanceToRegular == Int.MAX_VALUE) null else it to distanceToRegular
|
||||
}.minByOrNull { it.second }?.first
|
||||
if (font != null) {
|
||||
Typeface.CustomFallbackBuilder(FontFamily.Builder(font).build())
|
||||
.setSystemFallback(fontFamily).build()
|
||||
} else Typeface.create(fontFamily, Typeface.NORMAL)
|
||||
} else Typeface.create(fontFamily, Typeface.NORMAL)
|
||||
|
||||
isAntiAlias = true
|
||||
textSize = size.toFloat()
|
||||
strokeWidth = 0f
|
||||
setARGB(255, 255, 255, 255)
|
||||
if (font != null)
|
||||
{
|
||||
return Typeface.CustomFallbackBuilder(FontFamily.Builder(font).build())
|
||||
.setSystemFallback(name).build()
|
||||
}
|
||||
}
|
||||
return Typeface.create(name, Typeface.NORMAL)
|
||||
}
|
||||
|
||||
private fun createTypefaceCustom(path: String): Typeface {
|
||||
return try
|
||||
{
|
||||
Typeface.createFromFile(Gdx.files.local(path).file())
|
||||
}
|
||||
catch (e: Exception)
|
||||
{
|
||||
// Falling back to default
|
||||
Typeface.create(Fonts.DEFAULT_FONT_FAMILY, Typeface.NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper within the VERSION_CODES.Q gate: Evaluate a Font's desirability (lower = better) for a given family. */
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
private fun Font.matchesFamily(family: String): Int {
|
||||
val name = file?.nameWithoutExtension ?: return Int.MAX_VALUE
|
||||
if (name == family) return 0
|
||||
if (!name.startsWith("$family-")) return Int.MAX_VALUE
|
||||
if (style.weight == FontStyle.FONT_WEIGHT_NORMAL && style.slant == FontStyle.FONT_SLANT_UPRIGHT) return 1
|
||||
return 2 +
|
||||
abs(style.weight - FontStyle.FONT_WEIGHT_NORMAL) / 100 +
|
||||
abs(style.slant - FontStyle.FONT_SLANT_UPRIGHT)
|
||||
}
|
||||
|
||||
override fun getFontSize(): Int {
|
||||
return size
|
||||
return paint.textSize.toInt()
|
||||
}
|
||||
|
||||
override fun getCharPixmap(char: Char): Pixmap {
|
||||
@ -65,7 +105,7 @@ class NativeFontAndroid(
|
||||
var width = paint.measureText(char.toString()).toInt()
|
||||
var height = (metric.descent - metric.ascent).toInt()
|
||||
if (width == 0) {
|
||||
height = size
|
||||
height = getFontSize()
|
||||
width = height
|
||||
}
|
||||
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
@ -84,7 +124,7 @@ class NativeFontAndroid(
|
||||
return pixmap
|
||||
}
|
||||
|
||||
override fun getAvailableFontFamilies(): Sequence<FontFamilyData> {
|
||||
override fun getSystemFonts(): Sequence<FontFamilyData> {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
|
||||
return sequenceOf(FontFamilyData("sans-serif"), FontFamilyData("serif"), FontFamilyData("mono"))
|
||||
|
@ -27,6 +27,7 @@ import com.unciv.ui.audio.MusicController
|
||||
import com.unciv.ui.audio.MusicMood
|
||||
import com.unciv.ui.audio.MusicTrackChooserFlags
|
||||
import com.unciv.ui.audio.SoundPlayer
|
||||
import com.unciv.ui.components.FontImplementation
|
||||
import com.unciv.ui.crashhandling.CrashScreen
|
||||
import com.unciv.ui.crashhandling.wrapCrashHandlingUnit
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
@ -73,6 +74,10 @@ object GUI {
|
||||
return UncivGame.Current.settings
|
||||
}
|
||||
|
||||
fun getFontImpl(): FontImplementation {
|
||||
return UncivGame.Current.fontImplementation!!
|
||||
}
|
||||
|
||||
fun isWorldLoaded(): Boolean {
|
||||
return UncivGame.Current.worldScreen != null
|
||||
}
|
||||
@ -216,7 +221,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
|
||||
// Loading available fonts can take a long time on Android phones.
|
||||
// Therefore we initialize the lazy parameters in the font implementation, while we're in another thread, to avoid ANRs on main thread
|
||||
fontImplementation?.getCharPixmap('S')
|
||||
fontImplementation?.setFontFamily(settings.fontFamilyData, settings.getFontSize())
|
||||
|
||||
// This stuff needs to run on the main thread because it needs the GL context
|
||||
launchOnGLThread {
|
||||
|
@ -4,11 +4,11 @@ import com.unciv.logic.files.CustomFileLocationHelper
|
||||
import com.unciv.ui.crashhandling.CrashReportSysInfo
|
||||
import com.unciv.ui.components.AudioExceptionHelper
|
||||
import com.unciv.ui.components.GeneralPlatformSpecificHelpers
|
||||
import com.unciv.ui.components.NativeFontImplementation
|
||||
import com.unciv.ui.components.FontImplementation
|
||||
|
||||
class UncivGameParameters(val crashReportSysInfo: CrashReportSysInfo? = null,
|
||||
val cancelDiscordEvent: (() -> Unit)? = null,
|
||||
val fontImplementation: NativeFontImplementation? = null,
|
||||
val fontImplementation: FontImplementation? = null,
|
||||
val consoleMode: Boolean = false,
|
||||
val customFileLocationHelper: CustomFileLocationHelper? = null,
|
||||
val platformSpecificHelper: GeneralPlatformSpecificHelpers? = null,
|
||||
|
@ -6,6 +6,7 @@ import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.multiplayer.FriendList
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.ui.components.FontFamilyData
|
||||
import com.unciv.ui.components.Fonts
|
||||
import java.text.Collator
|
||||
import java.time.Duration
|
||||
@ -96,7 +97,7 @@ class GameSettings {
|
||||
/** Saves the last successful new game's setup */
|
||||
var lastGameSetup: GameSetupInfo? = null
|
||||
|
||||
var fontFamily: String = Fonts.DEFAULT_FONT_FAMILY
|
||||
var fontFamilyData: FontFamilyData = FontFamilyData.default
|
||||
var fontSizeMultiplier: Float = 1f
|
||||
|
||||
var enableEasterEggs: Boolean = true
|
||||
@ -139,6 +140,10 @@ class GameSettings {
|
||||
}
|
||||
}
|
||||
|
||||
fun getFontSize(): Int {
|
||||
return (Fonts.ORIGINAL_FONT_SIZE * fontSizeMultiplier).toInt()
|
||||
}
|
||||
|
||||
fun getCurrentLocale(): Locale {
|
||||
if (locale == null)
|
||||
updateLocaleFromLanguage()
|
||||
|
@ -12,15 +12,24 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import com.badlogic.gdx.utils.Array
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import com.unciv.Constants
|
||||
import com.unciv.GUI
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
|
||||
interface NativeFontImplementation {
|
||||
|
||||
interface FontImplementation {
|
||||
fun setFontFamily(fontFamilyData: FontFamilyData, size: Int)
|
||||
fun getFontSize(): Int
|
||||
fun getCharPixmap(char: Char): Pixmap
|
||||
fun getAvailableFontFamilies(): Sequence<FontFamilyData>
|
||||
fun getSystemFonts(): Sequence<FontFamilyData>
|
||||
|
||||
fun getBitmapFont(): BitmapFont {
|
||||
val fontData = NativeBitmapFontData(this)
|
||||
val font = BitmapFont(fontData, fontData.regions, false)
|
||||
font.setOwnsTexture(true)
|
||||
return font
|
||||
}
|
||||
}
|
||||
|
||||
// If save in `GameSettings` need use invariantFamily.
|
||||
@ -28,8 +37,13 @@ interface NativeFontImplementation {
|
||||
// If save localName in `GameSettings` may generate garbled characters by encoding.
|
||||
class FontFamilyData(
|
||||
val localName: String,
|
||||
val invariantName: String = localName
|
||||
val invariantName: String = localName,
|
||||
val filePath: String? = null
|
||||
) {
|
||||
|
||||
// For serialization
|
||||
constructor() : this(default.localName, default.invariantName)
|
||||
|
||||
// Implement kotlin equality contract such that _only_ the invariantName field is compared.
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other is FontFamilyData) invariantName == other.invariantName
|
||||
@ -39,16 +53,16 @@ class FontFamilyData(
|
||||
override fun hashCode() = invariantName.hashCode()
|
||||
|
||||
/** For SelectBox usage */
|
||||
override fun toString() = localName
|
||||
override fun toString() = localName.tr()
|
||||
|
||||
companion object {
|
||||
val default = FontFamilyData("Default Font".tr(), Fonts.DEFAULT_FONT_FAMILY)
|
||||
val default = FontFamilyData("Default Font", Fonts.DEFAULT_FONT_FAMILY)
|
||||
}
|
||||
}
|
||||
|
||||
// This class is loosely based on libgdx's FreeTypeBitmapFontData
|
||||
class NativeBitmapFontData(
|
||||
private val fontImplementation: NativeFontImplementation
|
||||
private val fontImplementation: FontImplementation
|
||||
) : BitmapFontData(), Disposable {
|
||||
|
||||
val regions: Array<TextureRegion>
|
||||
@ -80,6 +94,8 @@ class NativeBitmapFontData(
|
||||
// Set space glyph.
|
||||
val spaceGlyph = getGlyph(' ')
|
||||
spaceXadvance = spaceGlyph.xadvance.toFloat()
|
||||
|
||||
setScale(Constants.defaultFontSize / Fonts.ORIGINAL_FONT_SIZE)
|
||||
}
|
||||
|
||||
override fun getGlyph(ch: Char): Glyph {
|
||||
@ -167,29 +183,17 @@ object Fonts {
|
||||
* Do not call from normal code - reset the Skin instead: `BaseScreen.setSkin()`
|
||||
*/
|
||||
fun resetFont() {
|
||||
val fontData = NativeBitmapFontData(UncivGame.Current.fontImplementation!!)
|
||||
font = BitmapFont(fontData, fontData.regions, false)
|
||||
font.setOwnsTexture(true)
|
||||
font.data.setScale(Constants.defaultFontSize / ORIGINAL_FONT_SIZE)
|
||||
}
|
||||
|
||||
/** This resets all cached font data and allows changing the font */
|
||||
fun resetFont(newFamily: String) {
|
||||
try {
|
||||
val fontImplementationClass = UncivGame.Current.fontImplementation!!::class.java
|
||||
val fontImplementationConstructor = fontImplementationClass.constructors.first()
|
||||
val newFontImpl = fontImplementationConstructor.newInstance((ORIGINAL_FONT_SIZE * UncivGame.Current.settings.fontSizeMultiplier).toInt(), newFamily)
|
||||
if (newFontImpl is NativeFontImplementation)
|
||||
UncivGame.Current.fontImplementation = newFontImpl
|
||||
} catch (ex: Exception) {}
|
||||
BaseScreen.setSkin() // calls our resetFont() - needed - the Skin seems to cache glyphs
|
||||
val settings = GUI.getSettings()
|
||||
val fontImpl = GUI.getFontImpl()
|
||||
fontImpl.setFontFamily(settings.fontFamilyData, settings.getFontSize())
|
||||
font = fontImpl.getBitmapFont()
|
||||
}
|
||||
|
||||
/** Reduce the font list returned by platform-specific code to font families (plain variant if possible) */
|
||||
fun getAvailableFontFamilyNames(): Sequence<FontFamilyData> {
|
||||
fun getSystemFonts(): Sequence<FontFamilyData> {
|
||||
val fontImplementation = UncivGame.Current.fontImplementation
|
||||
?: return emptySequence()
|
||||
return fontImplementation.getAvailableFontFamilies()
|
||||
return fontImplementation.getSystemFonts()
|
||||
.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.localName })
|
||||
}
|
||||
|
||||
|
@ -116,25 +116,57 @@ private fun addFontFamilySelect(table: Table, settings: GameSettings, selectBoxM
|
||||
// Therefore, _selecting_ an item in a `SelectBox` by an instance of `FontFamilyData` where only the `invariantName` is valid won't work properly.
|
||||
//
|
||||
// This is why it's _not_ `fontSelectBox.selected = FontFamilyData(settings.fontFamily)`
|
||||
val fontToSelect = settings.fontFamily
|
||||
fontSelectBox.selected = fonts.firstOrNull { it.invariantName == fontToSelect } // will default to first entry if `null` is passed
|
||||
val fontToSelect = settings.fontFamilyData
|
||||
fontSelectBox.selected = fonts.firstOrNull { it.invariantName == fontToSelect.invariantName } // will default to first entry if `null` is passed
|
||||
|
||||
selectCell.setActor(fontSelectBox).minWidth(selectBoxMinWidth).pad(10f)
|
||||
|
||||
fontSelectBox.onChange {
|
||||
settings.fontFamily = fontSelectBox.selected.invariantName
|
||||
Fonts.resetFont(settings.fontFamily)
|
||||
settings.fontFamilyData = fontSelectBox.selected
|
||||
onFontChange()
|
||||
}
|
||||
}
|
||||
|
||||
// This is a heavy operation and causes ANRs
|
||||
Concurrency.run("Add Font Select") {
|
||||
// This is a heavy operation and causes ANRs
|
||||
val fonts = Array<FontFamilyData>().apply {
|
||||
add(FontFamilyData.default)
|
||||
for (font in Fonts.getAvailableFontFamilyNames())
|
||||
add(font)
|
||||
|
||||
val fonts = Array<FontFamilyData>()
|
||||
|
||||
// Add default font
|
||||
fonts.add(FontFamilyData.default)
|
||||
|
||||
// Add mods fonts
|
||||
val modsDir = Gdx.files.local("mods/")
|
||||
for (mod in modsDir.list()) {
|
||||
|
||||
// Not a dir, continue
|
||||
if (!mod.isDirectory)
|
||||
continue
|
||||
|
||||
val modFontsDir = mod.child("fonts")
|
||||
|
||||
// Mod doesn't have fonts, continue
|
||||
if (!modFontsDir.exists())
|
||||
continue
|
||||
|
||||
// Find .ttf files and add construct FontFamilyData
|
||||
for (fontFile in modFontsDir.list()) {
|
||||
if (fontFile.extension().lowercase() == "ttf") {
|
||||
fonts.add(
|
||||
FontFamilyData(
|
||||
"${fontFile.nameWithoutExtension()} (${mod.name()})",
|
||||
fontFile.nameWithoutExtension(),
|
||||
fontFile.path())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add system fonts
|
||||
for (font in Fonts.getSystemFonts())
|
||||
fonts.add(font)
|
||||
|
||||
launchOnGLThread { loadFontSelect(fonts, selectCell) }
|
||||
}
|
||||
}
|
||||
@ -154,10 +186,8 @@ private fun addFontSizeMultiplier(
|
||||
settings.save()
|
||||
}
|
||||
fontSizeSlider.onChange {
|
||||
if (!fontSizeSlider.isDragging) {
|
||||
Fonts.resetFont(settings.fontFamily)
|
||||
if (!fontSizeSlider.isDragging)
|
||||
onFontChange()
|
||||
}
|
||||
}
|
||||
table.add(fontSizeSlider).pad(5f).row()
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import com.unciv.logic.files.SETTINGS_FILE_NAME
|
||||
import com.unciv.logic.files.UncivFiles
|
||||
import com.unciv.models.metadata.ScreenSize
|
||||
import com.unciv.models.metadata.WindowState
|
||||
import com.unciv.ui.components.Fonts
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.debug
|
||||
import java.awt.GraphicsEnvironment
|
||||
@ -73,7 +72,7 @@ internal object DesktopLauncher {
|
||||
val platformSpecificHelper = PlatformSpecificHelpersDesktop(config)
|
||||
val desktopParameters = UncivGameParameters(
|
||||
cancelDiscordEvent = { discordTimer?.cancel() },
|
||||
fontImplementation = NativeFontDesktop((Fonts.ORIGINAL_FONT_SIZE * settings.fontSizeMultiplier).toInt(), settings.fontFamily),
|
||||
fontImplementation = FontDesktop(),
|
||||
customFileLocationHelper = CustomFileLocationHelperDesktop(),
|
||||
crashReportSysInfo = CrashReportSysInfoDesktop(),
|
||||
platformSpecificHelper = platformSpecificHelper,
|
||||
|
61
desktop/src/com/unciv/app/desktop/NativeFontDesktop.kt → desktop/src/com/unciv/app/desktop/FontDesktop.kt
Executable file → Normal file
61
desktop/src/com/unciv/app/desktop/NativeFontDesktop.kt → desktop/src/com/unciv/app/desktop/FontDesktop.kt
Executable file → Normal file
@ -1,35 +1,66 @@
|
||||
package com.unciv.app.desktop
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.unciv.ui.components.FontFamilyData
|
||||
import com.unciv.ui.components.NativeFontImplementation
|
||||
import com.unciv.ui.components.FontImplementation
|
||||
import com.unciv.ui.components.Fonts
|
||||
import java.awt.*
|
||||
import java.awt.image.BufferedImage
|
||||
import java.util.*
|
||||
|
||||
class NativeFontDesktop(private val size: Int, private val fontFamily: String) :
|
||||
NativeFontImplementation {
|
||||
private val font by lazy {
|
||||
Font(fontFamily, Font.PLAIN, size)
|
||||
|
||||
class FontDesktop : FontImplementation {
|
||||
|
||||
private lateinit var font: Font
|
||||
private lateinit var metric: FontMetrics
|
||||
|
||||
override fun setFontFamily(fontFamilyData: FontFamilyData, size: Int) {
|
||||
|
||||
// Mod font
|
||||
if (fontFamilyData.filePath != null)
|
||||
{
|
||||
this.font = createFontFromFile(fontFamilyData.filePath!!, size)
|
||||
}
|
||||
// System font
|
||||
else
|
||||
{
|
||||
this.font = Font(fontFamilyData.invariantName, Font.PLAIN, size)
|
||||
}
|
||||
|
||||
val bufferedImage = BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)
|
||||
val graphics = bufferedImage.createGraphics()
|
||||
this.metric = graphics.getFontMetrics(font)
|
||||
graphics.dispose()
|
||||
}
|
||||
private val metric by lazy {
|
||||
val bi = BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)
|
||||
val g = bi.createGraphics()
|
||||
g.font = font
|
||||
val fontMetrics = g.fontMetrics
|
||||
g.dispose()
|
||||
fontMetrics
|
||||
|
||||
private fun createFontFromFile(path: String, size: Int): Font {
|
||||
var font: Font
|
||||
try
|
||||
{
|
||||
// Try to create and register new font
|
||||
val fontFile = Gdx.files.local(path).file()
|
||||
val ge = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
font = Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(size.toFloat())
|
||||
ge.registerFont(font)
|
||||
}
|
||||
catch (e: Exception)
|
||||
{
|
||||
// Fallback to default, if failed.
|
||||
font = Font(Fonts.DEFAULT_FONT_FAMILY, Font.PLAIN, size)
|
||||
}
|
||||
return font
|
||||
}
|
||||
|
||||
override fun getFontSize(): Int {
|
||||
return size
|
||||
return font.size
|
||||
}
|
||||
|
||||
override fun getCharPixmap(char: Char): Pixmap {
|
||||
var width = metric.charWidth(char)
|
||||
var height = metric.ascent + metric.descent
|
||||
if (width == 0) {
|
||||
height = size
|
||||
height = font.size
|
||||
width = height
|
||||
}
|
||||
val bi = BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR)
|
||||
@ -50,7 +81,7 @@ class NativeFontDesktop(private val size: Int, private val fontFamily: String) :
|
||||
return pixmap
|
||||
}
|
||||
|
||||
override fun getAvailableFontFamilies(): Sequence<FontFamilyData> {
|
||||
override fun getSystemFonts(): Sequence<FontFamilyData> {
|
||||
val cjkLanguage = " CJK " +System.getProperty("user.language").uppercase()
|
||||
return GraphicsEnvironment.getLocalGraphicsEnvironment().allFonts.asSequence()
|
||||
.filter { " CJK " !in it.fontName || cjkLanguage in it.fontName }
|
@ -19,7 +19,7 @@ import com.unciv.ui.images.ImageWithCustomSize
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.components.FontFamilyData
|
||||
import com.unciv.ui.components.Fonts
|
||||
import com.unciv.ui.components.NativeFontImplementation
|
||||
import com.unciv.ui.components.FontImplementation
|
||||
import com.unciv.ui.components.extensions.center
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.utils.concurrency.Concurrency
|
||||
@ -62,7 +62,7 @@ object FasterUIDevelopment {
|
||||
|
||||
class UIDevGame : Game() {
|
||||
val game = UncivGame(UncivGameParameters(
|
||||
fontImplementation = NativeFontDesktop()
|
||||
fontImplementation = FontDesktop()
|
||||
))
|
||||
override fun create() {
|
||||
UncivGame.Current = game
|
||||
@ -126,7 +126,7 @@ object FasterUIDevelopment {
|
||||
}
|
||||
|
||||
|
||||
class NativeFontDesktop : NativeFontImplementation {
|
||||
class FontDesktop : FontImplementation {
|
||||
private val font by lazy {
|
||||
Font(Fonts.DEFAULT_FONT_FAMILY, Font.PLAIN, Fonts.ORIGINAL_FONT_SIZE.toInt())
|
||||
}
|
||||
@ -139,6 +139,10 @@ class NativeFontDesktop : NativeFontImplementation {
|
||||
fontMetrics
|
||||
}
|
||||
|
||||
override fun setFontFamily(fontFamilyData: FontFamilyData, size: Int) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
override fun getFontSize(): Int {
|
||||
return Fonts.ORIGINAL_FONT_SIZE.toInt()
|
||||
}
|
||||
@ -168,7 +172,7 @@ class NativeFontDesktop : NativeFontImplementation {
|
||||
return pixmap
|
||||
}
|
||||
|
||||
override fun getAvailableFontFamilies(): Sequence<FontFamilyData> {
|
||||
override fun getSystemFonts(): Sequence<FontFamilyData> {
|
||||
return sequenceOf(FontFamilyData(Fonts.DEFAULT_FONT_FAMILY))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user