mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 15:27:50 +07:00
Rewrite the font system to render the characters incrementally (#2635)
This commit is contained in:
@ -15,7 +15,6 @@ import java.util.*
|
||||
import kotlin.concurrent.timer
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
internal object DesktopLauncher {
|
||||
private var discordTimer: Timer? = null
|
||||
|
||||
@ -32,7 +31,7 @@ internal object DesktopLauncher {
|
||||
|
||||
val versionFromJar = DesktopLauncher.javaClass.`package`.specificationVersion ?: "Desktop"
|
||||
|
||||
val game = UncivGame ( versionFromJar, null, { exitProcess(0) }, { discordTimer?.cancel() } )
|
||||
val game = UncivGame ( versionFromJar, null, { exitProcess(0) }, { discordTimer?.cancel() }, NativeFontDesktop(45) )
|
||||
|
||||
if(!RaspberryPiDetector.isRaspberryPi()) // No discord RPC for Raspberry Pi, see https://github.com/yairm210/Unciv/issues/1624
|
||||
tryActivateDiscord(game)
|
||||
|
47
desktop/src/com/unciv/app/desktop/NativeFontDesktop.kt
Executable file
47
desktop/src/com/unciv/app/desktop/NativeFontDesktop.kt
Executable file
@ -0,0 +1,47 @@
|
||||
package com.unciv.app.desktop
|
||||
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.unciv.ui.utils.NativeFontImplementation
|
||||
import java.awt.*
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
|
||||
class NativeFontDesktop(val size: Int) : NativeFontImplementation {
|
||||
private val font by lazy {
|
||||
Font("", Font.PLAIN, size)
|
||||
}
|
||||
private val metric by lazy {
|
||||
val bi = BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)
|
||||
val g = bi.createGraphics()
|
||||
g.font = font
|
||||
g.fontMetrics!!
|
||||
}
|
||||
|
||||
override fun getFontSize(): Int {
|
||||
return size
|
||||
}
|
||||
|
||||
override fun getCharPixmap(char: Char): Pixmap {
|
||||
var width = metric.charWidth(char)
|
||||
var height = metric.ascent + metric.descent
|
||||
if (width == 0) {
|
||||
height = size
|
||||
width = height
|
||||
}
|
||||
val bi = BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR)
|
||||
val g = bi.createGraphics()
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
||||
g.font = font
|
||||
g.color = Color.WHITE
|
||||
g.drawString(char.toString(), 0, metric.ascent)
|
||||
val pixmap = Pixmap(bi.width, bi.height, Pixmap.Format.RGBA8888)
|
||||
val data = bi.getRGB(0, 0, bi.width, bi.height, null, 0, bi.width)
|
||||
for (i in 0 until bi.width) {
|
||||
for (j in 0 until bi.height) {
|
||||
pixmap.setColor(Integer.reverseBytes(data[i + (j * bi.width)]))
|
||||
pixmap.drawPixel(i, j)
|
||||
}
|
||||
}
|
||||
return pixmap
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package core.java.nativefont
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import java.awt.*
|
||||
import java.awt.font.TextAttribute
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
import java.text.AttributedString
|
||||
import java.util.*
|
||||
import javax.imageio.ImageIO
|
||||
import javax.swing.UIManager
|
||||
|
||||
class NativeFontDesktop : NativeFontListener {
|
||||
private val fonts = HashMap<String, Font?>()
|
||||
private val metrics = HashMap<String, FontMetrics>()
|
||||
override fun getFontPixmap(txt: String, vpaint: NativeFontPaint): Pixmap {
|
||||
val font = getFont(vpaint)
|
||||
val fm = metrics[vpaint.name]
|
||||
var strWidth = fm!!.stringWidth(txt)
|
||||
var strHeight = fm.ascent + fm.descent
|
||||
if (strWidth == 0) {
|
||||
strHeight = vpaint.textSize
|
||||
strWidth = strHeight
|
||||
}
|
||||
val bi = BufferedImage(strWidth, strHeight, BufferedImage.TYPE_4BYTE_ABGR)
|
||||
val g = bi.createGraphics()
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
||||
g.font = font
|
||||
when {
|
||||
vpaint.strokeColor != null -> { // 描边
|
||||
val v = font!!.createGlyphVector(fm.fontRenderContext, txt)
|
||||
val shape = v.outline
|
||||
g.color = UIManager.getColor(vpaint.color)
|
||||
g.translate(0, fm.ascent)
|
||||
g.fill(shape)
|
||||
g.stroke = BasicStroke(vpaint.strokeWidth.toFloat())
|
||||
g.color = UIManager.getColor(vpaint.strokeColor)
|
||||
g.draw(shape)
|
||||
}
|
||||
vpaint.underlineText -> { // 下划线
|
||||
val `as` = AttributedString(txt)
|
||||
`as`.addAttribute(TextAttribute.FONT, font)
|
||||
`as`.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON)
|
||||
g.color = UIManager.getColor(vpaint.color)
|
||||
g.drawString(`as`.iterator, 0, fm.ascent)
|
||||
}
|
||||
vpaint.strikeThruText -> { // 删除线
|
||||
val `as` = AttributedString(txt)
|
||||
`as`.addAttribute(TextAttribute.FONT, font)
|
||||
`as`.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON)
|
||||
g.color = UIManager.getColor(vpaint.color)
|
||||
g.drawString(`as`.iterator, 0, fm.ascent)
|
||||
}
|
||||
else -> { // 普通
|
||||
g.color = UIManager.getColor(vpaint.color)
|
||||
g.drawString(txt, 0, fm.ascent)
|
||||
}
|
||||
}
|
||||
lateinit var pixmap: Pixmap
|
||||
try {
|
||||
val buffer = ByteArrayOutputStream()
|
||||
ImageIO.write(bi, "png", buffer)
|
||||
pixmap = Pixmap(buffer.toByteArray(), 0, buffer.toByteArray().size)
|
||||
buffer.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return pixmap
|
||||
}
|
||||
|
||||
private fun getFont(vpaint: NativeFontPaint): Font? {
|
||||
val isBolo = vpaint.fakeBoldText || vpaint.strokeColor != null
|
||||
var font = fonts[vpaint.name]
|
||||
if (font == null) {
|
||||
if (vpaint.tTFName == "") {
|
||||
font = Font("", if (isBolo) Font.BOLD else Font.PLAIN, vpaint.textSize)
|
||||
} else {
|
||||
try {
|
||||
val `in` = ByteArrayInputStream(Gdx.files.internal(vpaint.tTFName +
|
||||
if (vpaint.tTFName.endsWith(".ttf")) "" else ".ttf").readBytes())
|
||||
val fb = BufferedInputStream(`in`)
|
||||
font = Font.createFont(Font.TRUETYPE_FONT, fb).deriveFont(Font.BOLD, vpaint.textSize.toFloat())
|
||||
fb.close()
|
||||
`in`.close()
|
||||
} catch (e: FontFormatException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
fonts[vpaint.name] = font
|
||||
val bi = BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)
|
||||
val g = bi.createGraphics()
|
||||
g.font = font
|
||||
val fm = g.fontMetrics
|
||||
metrics[vpaint.name] = fm
|
||||
}
|
||||
return font
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user