mirror of
https://github.com/curioustorvald/Terrarum-sans-bitmap.git
synced 2026-06-10 07:54:05 +09:00
freezing slugs into a single line of text
This commit is contained in:
@@ -3,11 +3,11 @@ package net.torvald.terrarumsansbitmap
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.Batch
|
import com.badlogic.gdx.graphics.g2d.Batch
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import net.torvald.terrarumsansbitmap.MovableType.Companion.isGlue
|
||||||
import net.torvald.terrarumsansbitmap.gdx.CodePoint
|
import net.torvald.terrarumsansbitmap.gdx.CodePoint
|
||||||
import net.torvald.terrarumsansbitmap.gdx.CodepointSequence
|
import net.torvald.terrarumsansbitmap.gdx.CodepointSequence
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.getHash
|
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.getHash
|
||||||
import java.lang.Math.log
|
|
||||||
import java.lang.Math.pow
|
import java.lang.Math.pow
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
@@ -28,7 +28,8 @@ class MovableType(
|
|||||||
var height = 0; private set
|
var height = 0; private set
|
||||||
internal val hash: Long = inputText.getHash()
|
internal val hash: Long = inputText.getHash()
|
||||||
private var disposed = false
|
private var disposed = false
|
||||||
val typesettedSlugs = ArrayList<List<Block>>()
|
// val typesettedSlugs = ArrayList<List<Block>>()
|
||||||
|
val typesettedSlugs = ArrayList<CodepointSequence>()
|
||||||
|
|
||||||
var width = 0; private set
|
var width = 0; private set
|
||||||
|
|
||||||
@@ -67,7 +68,8 @@ class MovableType(
|
|||||||
width = maxOf(width, nextPosX + box.width)
|
width = maxOf(width, nextPosX + box.width)
|
||||||
}
|
}
|
||||||
fun dispatchSlug() {
|
fun dispatchSlug() {
|
||||||
typesettedSlugs.add(slug)
|
// typesettedSlugs.add(slug)
|
||||||
|
typesettedSlugs.add(slug.freezeIntoCodepointSequence())
|
||||||
|
|
||||||
slug = ArrayList()
|
slug = ArrayList()
|
||||||
slugWidth = 0
|
slugWidth = 0
|
||||||
@@ -252,46 +254,24 @@ class MovableType(
|
|||||||
height = typesettedSlugs.size
|
height = typesettedSlugs.size
|
||||||
} }
|
} }
|
||||||
|
|
||||||
fun draw(batch: Batch, x: Int, y: Int, lineStart: Int = 0, linesToDraw: Int = 2147483647, lineHeight: Int = TerrarumSansBitmap.LINE_HEIGHT, drawJobs: Map<Int, (Float, Float, Int) -> Unit> = HashMap()) =
|
fun draw(batch: Batch, x: Int, y: Int, lineStart: Int = 0, linesToDraw: Int = 2147483647, lineHeight: Int = TerrarumSansBitmap.LINE_HEIGHT) =
|
||||||
draw(batch, x.toFloat(), y.toFloat(), lineStart, linesToDraw, lineHeight, drawJobs)
|
draw(batch, x.toFloat(), y.toFloat(), lineStart, linesToDraw, lineHeight)
|
||||||
|
|
||||||
fun draw(batch: Batch, x: Int, y: Int, drawJobs: Map<Int, (Float, Float, Int) -> Unit> = HashMap()) =
|
fun draw(batch: Batch, x: Int, y: Int) =
|
||||||
draw(batch, x.toFloat(), y.toFloat(), 0, 2147483647, TerrarumSansBitmap.LINE_HEIGHT, drawJobs)
|
draw(batch, x.toFloat(), y.toFloat(), 0, 2147483647, TerrarumSansBitmap.LINE_HEIGHT)
|
||||||
|
|
||||||
fun draw(batch: Batch, x: Float, y: Float, drawJobs: Map<Int, (Float, Float, Int) -> Unit> = HashMap()) =
|
fun draw(batch: Batch, x: Float, y: Float) =
|
||||||
draw(batch, x, y, 0, 2147483647, TerrarumSansBitmap.LINE_HEIGHT, drawJobs)
|
draw(batch, x, y, 0, 2147483647, TerrarumSansBitmap.LINE_HEIGHT)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param drawJobs Draw call for specific lines (absolute line). This takes the form of Map from linnumber to draw function,
|
* @param drawJobs Draw call for specific lines (absolute line). This takes the form of Map from linnumber to draw function,
|
||||||
* which has three arguments: (line's top-left position-x, line's top-left position-y, absolute line number)
|
* which has three arguments: (line's top-left position-x, line's top-left position-y, absolute line number)
|
||||||
*/
|
*/
|
||||||
fun draw(batch: Batch, x: Float, y: Float, lineStart: Int = 0, linesToDraw: Int = 2147483647, lineHeight: Int = TerrarumSansBitmap.LINE_HEIGHT, drawJobs: Map<Int, (Float, Float, Int) -> Unit> = HashMap()) {
|
fun draw(batch: Batch, x: Float, y: Float, lineStart: Int = 0, linesToDraw: Int = 2147483647, lineHeight: Int = TerrarumSansBitmap.LINE_HEIGHT) {
|
||||||
if (isNull) return
|
if (isNull) return
|
||||||
|
|
||||||
typesettedSlugs.subList(lineStart, minOf(typesettedSlugs.size, lineStart + linesToDraw)).forEachIndexed { lineNum, lineBlocks ->
|
typesettedSlugs.subList(lineStart, minOf(typesettedSlugs.size, lineStart + linesToDraw)).forEachIndexed { lineNum, text ->
|
||||||
// println("Line [${lineNum+1}] anchors: "+ lineBlocks.map { it.posX }.joinToString())
|
font.drawNormalised(batch, text, x, y + lineNum * lineHeight * font.scale)
|
||||||
|
|
||||||
val absoluteLineNum = lineStart + lineNum
|
|
||||||
|
|
||||||
drawJobs[absoluteLineNum]?.invoke(x, y + lineNum * lineHeight, absoluteLineNum)
|
|
||||||
|
|
||||||
lineBlocks.forEach {
|
|
||||||
lateinit var oldColour: Color
|
|
||||||
|
|
||||||
if (it.colour != null) {
|
|
||||||
oldColour = batch.color.cpy()
|
|
||||||
batch.color = it.colour
|
|
||||||
}
|
|
||||||
|
|
||||||
font.drawNormalised(batch,
|
|
||||||
it.block.text,
|
|
||||||
x + it.posX,
|
|
||||||
y + lineNum * lineHeight * font.scale
|
|
||||||
)
|
|
||||||
|
|
||||||
if (it.colour != null)
|
|
||||||
batch.color = oldColour
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,28 +431,7 @@ class MovableType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendoutGlue() {
|
fun sendoutGlue() {
|
||||||
if (glue == 0)
|
tokens.add(glue.glueSizeToGlueChars())
|
||||||
tokens.add(CodepointSequence(listOf((ZWSP))))
|
|
||||||
else if (glue.absoluteValue <= 16)
|
|
||||||
if (glue > 0)
|
|
||||||
tokens.add(CodepointSequence(listOf(GLUE_POSITIVE_ONE + (glue - 1))))
|
|
||||||
else
|
|
||||||
tokens.add(CodepointSequence(listOf(GLUE_NEGATIVE_ONE + (glue.absoluteValue - 1))))
|
|
||||||
else {
|
|
||||||
val fullGlues = glue.absoluteValue / 16
|
|
||||||
val smallGlues = glue.absoluteValue % 16
|
|
||||||
if (glue > 0)
|
|
||||||
tokens.add(CodepointSequence(
|
|
||||||
List(fullGlues) { GLUE_POSITIVE_SIXTEEN } +
|
|
||||||
listOf(GLUE_POSITIVE_ONE + (smallGlues - 1))
|
|
||||||
))
|
|
||||||
else
|
|
||||||
tokens.add(CodepointSequence(
|
|
||||||
List(fullGlues) { GLUE_NEGATIVE_SIXTEEN } +
|
|
||||||
listOf(GLUE_NEGATIVE_ONE + (smallGlues - 1))
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
glue = 0
|
glue = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,7 +669,7 @@ class MovableType(
|
|||||||
private fun CodepointSequence.isGlue() = this.size == 1 && (this[0] == ZWSP || this[0] in 0xFFFE0..0xFFFFF)
|
private fun CodepointSequence.isGlue() = this.size == 1 && (this[0] == ZWSP || this[0] in 0xFFFE0..0xFFFFF)
|
||||||
private fun CodepointSequence.isNotGlue() = !this.isGlue()
|
private fun CodepointSequence.isNotGlue() = !this.isGlue()
|
||||||
private fun CodepointSequence.isZeroGlue() = this.size == 1 && (this[0] == ZWSP)
|
private fun CodepointSequence.isZeroGlue() = this.size == 1 && (this[0] == ZWSP)
|
||||||
private fun CodePoint.toGlueSize() = when (this) {
|
private fun CodePoint.glueCharToGlueSize() = when (this) {
|
||||||
ZWSP -> 0
|
ZWSP -> 0
|
||||||
in 0xFFFE0..0xFFFEF -> -(this - 0xFFFE0 + 1)
|
in 0xFFFE0..0xFFFEF -> -(this - 0xFFFE0 + 1)
|
||||||
in 0xFFFF0..0xFFFFF -> this - 0xFFFF0 + 1
|
in 0xFFFF0..0xFFFFF -> this - 0xFFFF0 + 1
|
||||||
@@ -854,6 +813,8 @@ class MovableType(
|
|||||||
"{SHY}"
|
"{SHY}"
|
||||||
else if (it == ZWSP)
|
else if (it == ZWSP)
|
||||||
"{ZWSP}"
|
"{ZWSP}"
|
||||||
|
else if (it in GLUE_NEGATIVE_ONE..GLUE_POSITIVE_SIXTEEN)
|
||||||
|
" <glue ${it.glueCharToGlueSize()}> "
|
||||||
else if (it >= 0xF0000)
|
else if (it >= 0xF0000)
|
||||||
it.toHex() + " "
|
it.toHex() + " "
|
||||||
else
|
else
|
||||||
@@ -868,7 +829,7 @@ class MovableType(
|
|||||||
if (it.isEmpty())
|
if (it.isEmpty())
|
||||||
"<!! EMPTY !!>"
|
"<!! EMPTY !!>"
|
||||||
else if (it.isGlue())
|
else if (it.isGlue())
|
||||||
"<Glue ${it.first().toGlueSize()}>"
|
"<Glue ${it.first().glueCharToGlueSize()}>"
|
||||||
else
|
else
|
||||||
it.toReadable()
|
it.toReadable()
|
||||||
}
|
}
|
||||||
@@ -883,17 +844,77 @@ class MovableType(
|
|||||||
return this.text.isGlue()
|
return this.text.isGlue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Int.glueSizeToGlueChars(): CodepointSequence {
|
||||||
|
val tokens = CodepointSequence()
|
||||||
|
|
||||||
|
if (this == 0)
|
||||||
|
tokens.add(ZWSP)
|
||||||
|
else if (this.absoluteValue <= 16)
|
||||||
|
if (this > 0)
|
||||||
|
tokens.addAll(listOf(GLUE_POSITIVE_ONE + (this - 1)))
|
||||||
|
else
|
||||||
|
tokens.addAll(listOf(GLUE_NEGATIVE_ONE + (this.absoluteValue - 1)))
|
||||||
|
else {
|
||||||
|
val fullGlues = this.absoluteValue / 16
|
||||||
|
val smallGlues = this.absoluteValue % 16
|
||||||
|
if (this > 0)
|
||||||
|
tokens.addAll(
|
||||||
|
List(fullGlues) { GLUE_POSITIVE_SIXTEEN } +
|
||||||
|
listOf(GLUE_POSITIVE_ONE + (smallGlues - 1))
|
||||||
|
)
|
||||||
|
else
|
||||||
|
tokens.addAll(
|
||||||
|
List(fullGlues) { GLUE_NEGATIVE_SIXTEEN } +
|
||||||
|
listOf(GLUE_NEGATIVE_ONE + (smallGlues - 1))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<Block>.freezeIntoCodepointSequence(): CodepointSequence {
|
||||||
|
val out = CodepointSequence()
|
||||||
|
|
||||||
|
val input = this.filter { it.block.text.isNotGlue() }
|
||||||
|
|
||||||
|
// println("Blocks:")
|
||||||
|
// input.forEach {
|
||||||
|
// println("x ${it.posX}\te ${it.getEndPos()}\tw ${it.block.width}; ${it.block.text.toReadable()}")
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (input.isEmpty()) {
|
||||||
|
// println("FreezeSlugs: ${out.toReadable()}")
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// process line indents
|
||||||
|
if (input.first().posX > 0)
|
||||||
|
out.addAll(input.first().posX.glueSizeToGlueChars())
|
||||||
|
|
||||||
|
// process blocks
|
||||||
|
input.forEachIndexed { index, it ->
|
||||||
|
val posX = it.posX + 1
|
||||||
|
val prevEndPos = if (index == 0) 0 else input[index-1].getEndPos()
|
||||||
|
if (index > 0 && posX != prevEndPos) {
|
||||||
|
out.addAll((posX - prevEndPos).glueSizeToGlueChars())
|
||||||
|
}
|
||||||
|
out.addAll(it.block.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// println("FreezeSlugs: ${out.toReadable()}\n")
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
data class NoTexGlyphLayout(val text: CodepointSequence, val width: Int) {
|
||||||
|
val penultimateCharOrNull: CodePoint?
|
||||||
|
get() = text.getOrNull(text.size - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGlyphLayout(font: TerrarumSansBitmap, str: CodepointSequence): NoTexGlyphLayout {
|
||||||
|
return NoTexGlyphLayout(str, font.getWidth(str))
|
||||||
|
}
|
||||||
} // end of companion object
|
} // end of companion object
|
||||||
|
|
||||||
data class NoTexGlyphLayout(val text: CodepointSequence, val width: Int) {
|
|
||||||
val penultimateCharOrNull: CodePoint?
|
|
||||||
get() = text.getOrNull(text.size - 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createGlyphLayout(font: TerrarumSansBitmap, str: CodepointSequence): NoTexGlyphLayout {
|
|
||||||
return NoTexGlyphLayout(str, font.getWidth(str))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -750,6 +750,7 @@ class TerrarumSansBitmap(
|
|||||||
private fun buildWidthTableInternal() {
|
private fun buildWidthTableInternal() {
|
||||||
for (i in 0 until 16) {
|
for (i in 0 until 16) {
|
||||||
glyphProps[i] = GlyphProps(0)
|
glyphProps[i] = GlyphProps(0)
|
||||||
|
glyphProps[i + 16] = GlyphProps(0)
|
||||||
glyphProps[MOVABLE_BLOCK_1 + i] = GlyphProps(i + 1)
|
glyphProps[MOVABLE_BLOCK_1 + i] = GlyphProps(i + 1)
|
||||||
glyphProps[MOVABLE_BLOCK_M1 + i] = GlyphProps(-i - 1)
|
glyphProps[MOVABLE_BLOCK_M1 + i] = GlyphProps(-i - 1)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user