improve font scaling, TextComponent: fix size changing bugs

This commit is contained in:
Bixilon 2021-09-06 11:20:48 +02:00
parent e736e58001
commit bfeafe86ec
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
7 changed files with 80 additions and 16 deletions

View File

@ -32,6 +32,7 @@ class CharData(
val char: Char,
val texture: AbstractTexture,
val width: Int,
val scaledWidth: Int,
var uvStart: Vec2,
var uvEnd: Vec2,
) {
@ -86,7 +87,7 @@ class CharData(
val startPosition = Vec2(position) + shadowOffset
val endPosition = startPosition + Vec2(width, Font.CHAR_HEIGHT.toFloat())
val endPosition = startPosition + Vec2(scaledWidth, Font.CHAR_HEIGHT.toFloat())
val italic = style.formatting.contains(PreChatFormattingCodes.ITALIC)
@ -110,7 +111,7 @@ class CharData(
}
fun calculateWidth(style: TextStyle): Int {
var width = width.toFloat()
var width = scaledWidth.toFloat()
if (style.formatting.contains(PreChatFormattingCodes.SHADOWED)) {
width += SHADOW_OFFSET
}

View File

@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.font.CharData
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
import de.bixilon.minosoft.util.KUtil.asList
import de.bixilon.minosoft.util.KUtil.toDouble
@ -32,6 +33,7 @@ class BitmapFontProvider(
val height = data["height"]?.toInt() ?: 8
val ascent = data["ascent"].toDouble()
private val chars: MutableMap<Char, CharData> = mutableMapOf()
private val heightScale = Font.CHAR_HEIGHT.toFloat() / height
init {
val texture = renderWindow.textureManager.staticTextures.createTexture(data["file"].toResourceLocation().texture())
@ -85,11 +87,14 @@ class BitmapFontProvider(
width = EMPTY_CHAR_WIDTH
}
val scaledWidth = (width * heightScale).toInt()
val charData = CharData(
renderWindow = renderWindow,
char = char.toChar(),
texture = texture,
width = width,
scaledWidth = scaledWidth,
uvStart = uvStart,
uvEnd = uvEnd,
)

View File

@ -61,12 +61,15 @@ class LegacyUnicodeFontProvider(
y = yEnd,
)
val width = (charXEnd - charXStart)
val scaledWidth = (width * HEIGHT_SCALE).toInt()
val charData = CharData(
renderWindow = renderWindow,
char = char,
texture = texture,
width = (charXEnd - charXStart) / (CHAR_SIZE / Font.CHAR_HEIGHT),
width = width,
scaledWidth = scaledWidth,
uvStart = uvStart,
uvEnd = uvEnd,
)
@ -94,6 +97,7 @@ class LegacyUnicodeFontProvider(
private const val UNICODE_PAGE_SIZE = 256
private const val UNICODE_PAGES = 256
private const val CHAR_SIZE = 16
private const val HEIGHT_SCALE = Font.CHAR_HEIGHT.toFloat() / CHAR_SIZE
private val PIXEL = Vec2(1.0f) / UNICODE_PAGE_SIZE
override fun build(renderWindow: RenderWindow, data: Map<String, Any>): LegacyUnicodeFontProvider {

View File

@ -33,7 +33,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
*/
fun wrap(): Boolean {
val yAdd = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING
if (size.y + yAdd > element.prefMaxSize.y) {
if (size.y + yAdd > element.maxSize.y) {
return true
}
offset.x = initialOffset.x
@ -47,7 +47,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
* @return If the text can't fit into the layout anymore
*/
fun add(x: Int): Boolean {
if (offset.x - initialOffset.x + x > element.prefMaxSize.x) {
if (offset.x - initialOffset.x + x > element.maxSize.x) {
if (wrap()) {
return true
}
@ -84,13 +84,13 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
if (size.y == 0) {
size.y = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING
}
} else if (offset.x != initialOffset.x && add(Font.HORIZONTAL_SPACING)) {
} else if (offset.x != initialOffset.x && add(Font.HORIZONTAL_SPACING)) { // ToDo: Only add space when char fits
return
}
val width = charData.calculateWidth(text)
if (offset.x == initialOffset.x && offset.x - initialOffset.x + width > element.prefMaxSize.x) {
if (offset.x == initialOffset.x && offset.x - initialOffset.x + width > element.maxSize.x) {
return
}
consumer?.let { charData.render(offset, z, text, it) }

View File

@ -32,8 +32,8 @@ abstract class Element {
val ret = Vec2i.MAX
parent?.let {
ret.x = it.prefMaxSize.x
ret.y = it.prefMaxSize.y
ret.x = it.maxSize.x
ret.y = it.maxSize.y
}
val maxSize = Vec2i(prefMaxSize)

View File

@ -32,20 +32,57 @@ class TextElement(
override var textComponent: ChatComponent = ChatComponent.of("")
private set(value) {
size = minSize
if (value.message.isNotEmpty()) {
val size = Vec2i(0, 0)
ChatComponentRenderer.render(Vec2i(0, 0), Vec2i(0, 0), size, 0, this, renderWindow, null, value)
this.size = size
}
field = value
parent?.childChange(this)
prepare(value)
}
override var prefMaxSize: Vec2i
get() = super.prefMaxSize
set(value) {
super.prefMaxSize = value
checkSize()
}
override var minSize: Vec2i
get() = super.minSize
set(value) {
super.minSize = value
checkSize()
}
init {
textComponent = ChatComponent.of(text)
}
private fun prepare(text: ChatComponent = textComponent) {
size = minSize
if (text.message.isNotEmpty()) {
val size = Vec2i(0, 0)
ChatComponentRenderer.render(Vec2i(0, 0), Vec2i(0, 0), size, 0, this, renderWindow, null, text)
this.size = size
}
parent?.childChange(this)
}
private fun checkSize() {
val size = Vec2i(size)
if (size.x > maxSize.x) {
return prepare()
}
if (size.y > maxSize.y) {
return prepare()
}
if (size.x < minSize.x) {
return prepare()
}
if (size.y < minSize.y) {
return prepare()
}
}
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
ChatComponentRenderer.render(Vec2i(offset), offset, Vec2i(0, 0), z, this, renderWindow, consumer, textComponent)
@ -53,6 +90,10 @@ class TextElement(
return LAYERS
}
override fun toString(): String {
return textComponent.toString()
}
companion object {
const val LAYERS = 4 // 1 layer for the text, 1 for strikethrough. * 2 for shadow
}

View File

@ -96,6 +96,17 @@ class HUDRenderer(
val text3 = TextElement(
renderWindow = renderWindow,
text = TextComponent(
message = "!T→E↓S←T~_OÄBÖMÜ",
color = ChatColors.YELLOW,
formatting = mutableSetOf(
PreChatFormattingCodes.UNDERLINED,
),
),
)
val text4 = TextElement(
renderWindow = renderWindow,
text = TextComponent(
message = "Noch viel längerer dummy normaler Text!",
@ -107,6 +118,7 @@ class HUDRenderer(
),
)
text3.prefMaxSize = Vec2i(50, Int.MAX_VALUE)
text4.prefMaxSize = Vec2i(50, Int.MAX_VALUE)
// ToDo: size > maxSize
@ -115,6 +127,7 @@ class HUDRenderer(
layout += text1
layout += text2
layout += text3
layout += text4
layout.render(Vec2i(0, 0), 0, mesh)