text wrapping fixes

This commit is contained in:
Bixilon 2023-06-13 22:10:51 +02:00
parent 8ce641cacf
commit e346f06c67
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
3 changed files with 90 additions and 12 deletions

View File

@ -185,5 +185,72 @@ class ChatComponentRendererTest {
)
}
fun `no space x`() {
val info = render(TextComponent("bcd\n\nefgh"), maxSize = Vec2(0.0f, Float.MAX_VALUE))
info.assert(
lineIndex = 0,
lines = listOf(),
size = Vec2(0.0f, 0.0f),
cutOff = true,
)
}
fun `no space y`() {
val info = render(TextComponent("bcd\n\nefgh"), maxSize = Vec2(Float.MAX_VALUE, 0.0f))
info.assert(
lineIndex = 0,
lines = listOf(),
size = Vec2(0.0f, 0.0f),
cutOff = true,
)
}
fun `no space`() {
val info = render(TextComponent("bcd\n\nefgh"), maxSize = Vec2(0.0f, 0.0f))
info.assert(
lineIndex = 0,
lines = listOf(),
size = Vec2(0.0f, 0.0f),
cutOff = true,
)
}
fun `size limit one line`() {
val info = render(TextComponent("bcd\nefgh"), maxSize = Vec2(Float.MAX_VALUE, 11.0f))
info.assert(
lineIndex = 0,
lines = listOf(
TextLineInfo(BaseComponent(TextComponent("bcd")), 5.0f),
),
size = Vec2(5.0f, 11.0f),
cutOff = true,
)
}
fun `size limit one line with overflow`() {
val info = render(TextComponent("bcd\nefgh"), maxSize = Vec2(5.0f, 11.0f))
info.assert(
lineIndex = 0,
lines = listOf(
TextLineInfo(BaseComponent(TextComponent("bcd")), 5.0f),
),
size = Vec2(5.0f, 11.0f),
cutOff = true,
)
}
fun `size limit two line`() {
val info = render(TextComponent("bcd\nefgh\nabc"), maxSize = Vec2(Float.MAX_VALUE, 22.0f))
info.assert(
lineIndex = 1,
lines = listOf(
TextLineInfo(BaseComponent(TextComponent("bcd")), 5.0f),
TextLineInfo(BaseComponent(TextComponent("efgh")), 14.0f),
),
size = Vec2(14.0f, 22.0f),
cutOff = true,
)
}
// TODO: shadow, cutoff, underline, strikethrough, using with consumer, formatting (just basic, that is code point renderer's job)
}

View File

@ -43,7 +43,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
private fun renderNewline(properties: TextRenderProperties, offset: TextOffset, info: TextRenderInfo, updateSize: Boolean): Boolean {
val height = offset.getNextLineHeight(properties)
if (!offset.addLine(info, height)) {
if (!offset.addLine(info, properties.lineHeight, height)) {
info.cutOff = true
return true
}
@ -75,10 +75,13 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
val line = StringBuilder()
var filled = false
for (codePoint in text.message.codePoints()) {
val stream = text.message.codePoints().iterator()
while (stream.hasNext()) {
val codePoint = stream.nextInt()
if (codePoint == '\n'.code) {
val lineIndex = info.lineIndex
filled = renderNewline(properties, offset, info, consumer == null)
info.lines[info.lineIndex - 1].push(text, line)
info.lines[lineIndex].push(text, line)
skipWhitespaces = true
if (filled) break else continue
}
@ -98,11 +101,11 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
val lineIndex = info.lineIndex
val lineInfo = renderer.render(offset, color, properties, info, formatting, codePoint, consumer, options)
if (consumer != null) continue // already know that information
if (lineInfo == CodePointAddResult.BREAK) {
filled = true
break
}
if (consumer != null) continue // already know that information
if (lineIndex != info.lineIndex) {
// new line started

View File

@ -34,12 +34,16 @@ class TextOffset(
return fits(offset.x, initial.x, info.maxSize.x, width)
}
fun fitsY(info: TextRenderInfo, height: Float): Boolean {
return fits(offset.y, initial.y, info.maxSize.y, height)
fun fitsY(info: TextRenderInfo, offset: Float, height: Float): Boolean {
return fits(this.offset.y + offset, initial.y, info.maxSize.y, height)
}
fun canEverFit(info: TextRenderInfo, width: Float): Boolean {
return info.maxSize.x >= width
}
fun fitsInLine(properties: TextRenderProperties, info: TextRenderInfo, width: Float): Boolean {
return fitsX(info, width) && fitsY(info, properties.lineHeight)
return fitsX(info, width) && fitsY(info, 0.0f, properties.lineHeight)
}
fun getNextLineHeight(properties: TextRenderProperties): Float {
@ -49,11 +53,11 @@ class TextOffset(
return height
}
fun addLine(info: TextRenderInfo, height: Float): Boolean {
if (!fitsY(info, height)) return false
fun addLine(info: TextRenderInfo, offset: Float, height: Float): Boolean {
if (!fitsY(info, offset, height)) return false
offset.y += height
offset.x = initial.x
this.offset.y += height
this.offset.x = initial.x
info.lines += TextLineInfo()
info.lineIndex++
@ -62,8 +66,12 @@ class TextOffset(
fun canAdd(properties: TextRenderProperties, info: TextRenderInfo, width: Float, height: Float): CodePointAddResult {
if (!canEverFit(info, width)) {
info.cutOff = true
return CodePointAddResult.BREAK
}
if (fitsInLine(properties, info, width)) return CodePointAddResult.FINE
if (addLine(info, height) && fitsInLine(properties, info, width)) return CodePointAddResult.NEW_LINE
if (addLine(info, 0.0f, height) && fitsInLine(properties, info, width)) return CodePointAddResult.NEW_LINE
info.cutOff = true
return CodePointAddResult.BREAK