Align ruleset icons in text to font metrics (#10233)

* Try to respect actual font layout, so fontSizeMultiplier works for ruleset icons too

* Replace font-based nation symbol in top bar with statically sized actor

* Reuse getReadonlyPixmap in extractPixmapFromTextureRegion

* Tweak topbar selected civ vertical align to be more pleasing to the human eye

* FasterUIDevelopment missing implementation of FontMetricsCommon

* Address hardcoded pixel coordinates comment

* Readability and comment cleanup

* More readability changes
This commit is contained in:
SomeTroglodyte
2023-10-07 21:00:30 +02:00
committed by GitHub
parent 5db8489bcb
commit 49e2979427
7 changed files with 296 additions and 99 deletions

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Pixmap
import com.unciv.ui.components.FontFamilyData
import com.unciv.ui.components.FontImplementation
import com.unciv.ui.components.FontMetricsCommon
import com.unciv.ui.components.Fonts
import java.awt.Color
import java.awt.Font
@ -62,17 +63,20 @@ class DesktopFont : FontImplementation {
override fun getCharPixmap(char: Char): Pixmap {
var width = metric.charWidth(char)
var height = metric.ascent + metric.descent
var height = metric.height
if (width == 0) {
// This happens e.g. for the Tab character
height = font.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)
g.drawString(char.toString(), 0, metric.leading + 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) {
@ -92,4 +96,16 @@ class DesktopFont : FontImplementation {
.map { FontFamilyData(it.family, it.getFamily(Locale.ROOT)) }
.distinctBy { it.invariantName }
}
// Note: AWT uses the FontDesignMetrics implementation in our case, which has more precise
// float fields but rounds to integers to satisfy the interface.
// Additionally, the rounding is weird: x.049 rounds down, x.051 rounds up.
// There is no way around the privacy crap: FontUtilities.getFont2D(metric.font).getStrike(metric.font, metric.fontRenderContext).getFontMetrics() would work if that last method wasn't private too...
// Reflection is out too, since java.desktop refuses to open sun.font - we must die with rounding errors!
override fun getMetrics() = FontMetricsCommon(
ascent = metric.ascent.toFloat(),
descent = metric.descent.toFloat(),
height = metric.height.toFloat(),
leading = metric.leading.toFloat()
)
}