mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-16 16:46:07 +09:00
btex stuffs
This commit is contained in:
@@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarumsansbitmap.MovableType
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-10-28.
|
||||
@@ -17,7 +18,9 @@ class BTeXDocument {
|
||||
var papersize = "standard"
|
||||
|
||||
var pageWidth = 420
|
||||
var pageHeight = 25 * 24
|
||||
var lineHeight = 24
|
||||
var pageLines = 25
|
||||
var pageHeight = pageLines * lineHeight
|
||||
|
||||
companion object {
|
||||
val DEFAULT_PAGE_BACK = Color(0xe1e1d7ff.toInt())
|
||||
@@ -61,13 +64,18 @@ class BTeXPage(
|
||||
}
|
||||
}
|
||||
|
||||
data class MovableTypeDrawCall(val movableType: MovableType, val rowStart: Int, val rowEnd: Int) {
|
||||
fun draw(batch: SpriteBatch, x: Float, y: Float) {
|
||||
movableType.draw(batch, x, y, rowStart, rowEnd)
|
||||
}
|
||||
}
|
||||
|
||||
class BTeXDrawCall(
|
||||
val posX: Int,
|
||||
val posY: Int,
|
||||
val theme: String,
|
||||
val colour: Color,
|
||||
val font: BitmapFont,
|
||||
val text: String? = null,
|
||||
val text: MovableTypeDrawCall? = null,
|
||||
val texture: TextureRegion? = null,
|
||||
) {
|
||||
|
||||
@@ -82,7 +90,7 @@ class BTeXDrawCall(
|
||||
batch.color = colour
|
||||
|
||||
if (text != null && texture == null) {
|
||||
font.draw(batch, text, px, py)
|
||||
text.draw(batch, px, py)
|
||||
}
|
||||
else if (text == null && texture != null) {
|
||||
batch.draw(texture, px, py)
|
||||
|
||||
@@ -4,13 +4,16 @@ import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.btex.BTeXDocument
|
||||
import net.torvald.terrarum.btex.BTeXDrawCall
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import org.xml.sax.Attributes
|
||||
import org.xml.sax.InputSource
|
||||
import org.xml.sax.helpers.DefaultHandler
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import javax.xml.parsers.SAXParserFactory
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.full.declaredFunctions
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-10-28.
|
||||
@@ -27,18 +30,27 @@ object BTeXParser {
|
||||
return doc
|
||||
}
|
||||
|
||||
private class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() {
|
||||
operator fun invoke(string: String): BTeXDocument {
|
||||
val doc = BTeXDocument()
|
||||
val parser = SAXParserFactory.newDefaultInstance().newSAXParser()
|
||||
parser.parse(InputSource(StringReader(string)), BTeXHandler(doc))
|
||||
return doc
|
||||
}
|
||||
|
||||
internal class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() {
|
||||
private val DEFAULT_FONTCOL = Color(0x222222ff)
|
||||
private val LINE_HEIGHT = 24
|
||||
private val LINE_HEIGHT = doc.lineHeight
|
||||
|
||||
private var cover = ""
|
||||
private var inner = ""
|
||||
private var papersize = ""
|
||||
private var def = ""
|
||||
|
||||
private var pageWidth = 420
|
||||
private var pageLines = 25
|
||||
private var pageHeight = 25 * LINE_HEIGHT
|
||||
private var btexOpened = false
|
||||
|
||||
private var pageWidth = doc.pageWidth
|
||||
private var pageLines = doc.pageLines
|
||||
private var pageHeight = doc.pageHeight
|
||||
|
||||
private val blockLut = HashMap<String, ItemID>()
|
||||
|
||||
@@ -51,66 +63,93 @@ object BTeXParser {
|
||||
private var typeX = 0
|
||||
private var typeY = 0
|
||||
|
||||
private val elemOpeners: HashMap<String, KFunction<*>> = HashMap()
|
||||
private val elemClosers: HashMap<String, KFunction<*>> = HashMap()
|
||||
|
||||
init {
|
||||
BTeXHandler::class.declaredFunctions.filter { it.findAnnotation<OpenTag>() != null }.forEach {
|
||||
println("Tag opener: ${it.name}")
|
||||
elemOpeners[it.name] = it
|
||||
}
|
||||
|
||||
BTeXHandler::class.declaredFunctions.filter { it.findAnnotation<CloseTag>() != null }.forEach {
|
||||
println("Tag closer: ${it.name}")
|
||||
elemClosers[it.name] = it
|
||||
}
|
||||
}
|
||||
|
||||
private fun printdbg(message: String?) {
|
||||
val CSI = "\u001B[32m"
|
||||
val timeNow = System.currentTimeMillis()
|
||||
val ss = (timeNow / 1000) % 60
|
||||
val mm = (timeNow / 60000) % 60
|
||||
val hh = (timeNow / 3600000) % 24
|
||||
val ms = timeNow % 1000
|
||||
val out = this.javaClass.getSimpleName()
|
||||
val prompt = CSI + String.format("%02d:%02d:%02d.%03d [%s]%s ", hh, mm, ss, ms, out, App.csi0)
|
||||
if (message == null) {
|
||||
println(prompt + "null")
|
||||
}
|
||||
else {
|
||||
val indentation = " ".repeat(out.length + 16)
|
||||
val msgLines: Array<String> = message.toString().split("\\n".toRegex()).dropLastWhile { it.isEmpty() }
|
||||
.toTypedArray()
|
||||
for (i in msgLines.indices) {
|
||||
println((if (i == 0) prompt else indentation) + msgLines[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
|
||||
val tag = qName; if (tagStack.isEmpty() && tag != "btex") throw BTeXParsingException("Document is not btex")
|
||||
val tag = qName; if (tagStack.isEmpty() && tag.lowercase() != "btexdoc") throw BTeXParsingException("Document is not BTeX")
|
||||
tagStack.add(tag)
|
||||
|
||||
val attribs = HashMap<String, String>().also {
|
||||
it.putAll((0 until attributes.length).map { attributes.getQName(it) to attributes.getValue(it) })
|
||||
}
|
||||
|
||||
val mode = tagStack.getOrNull(1)
|
||||
val theTag = tag.uppercase()
|
||||
|
||||
when (tag) {
|
||||
"btex" -> {
|
||||
if (attribs.containsKey("def"))
|
||||
def = attribs["def"]!!
|
||||
else {
|
||||
cover = attribs["cover"] ?: "printout"
|
||||
inner = attribs["inner"] ?: "standard"
|
||||
papersize = attribs["papersize"] ?: "standard"
|
||||
|
||||
pageWidth = pageWidthMap[papersize]!!
|
||||
pageLines = pageHeightMap[papersize]!!
|
||||
pageHeight = pageLines * LINE_HEIGHT
|
||||
|
||||
doc.pageWidth = pageWidth
|
||||
doc.pageHeight = pageHeight
|
||||
elemOpeners["processElem$theTag"].let {
|
||||
if (it == null)
|
||||
System.err.println("Unknown tag: $theTag")
|
||||
else {
|
||||
try {
|
||||
it.call(this, this, doc, theTag, uri, attribs)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw BTeXParsingException(e.stackTraceToString())
|
||||
}
|
||||
}
|
||||
"pair" -> {
|
||||
if (tagStack.size == 3 && mode == "blocklut") {
|
||||
blockLut[attribs["key"]!!] = attribs["value"]!!
|
||||
}
|
||||
else {
|
||||
throw BTeXParsingException("<pair> used outside of <blocklut>")
|
||||
}
|
||||
}
|
||||
"span" -> {
|
||||
attribs["span"]?.let {
|
||||
spanColour = it
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// printdbg("Start element \t($tag)")
|
||||
}
|
||||
|
||||
override fun endElement(uri: String, localName: String, qName: String) {
|
||||
tagStack.removeLast()
|
||||
val popped = tagStack.removeLast()
|
||||
|
||||
when (qName) {
|
||||
"span" -> {
|
||||
spanColour = null
|
||||
val theTag = qName.uppercase()
|
||||
|
||||
elemClosers["closeElem$theTag"].let {
|
||||
try {
|
||||
it?.call(this, this, doc, theTag, uri)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw BTeXParsingException(e.stackTraceToString())
|
||||
}
|
||||
}
|
||||
|
||||
// printdbg(" End element \t($popped)")
|
||||
}
|
||||
|
||||
override fun characters(ch: CharArray, start: Int, length: Int) {
|
||||
val str = String(ch.sliceArray(start until start+length)).replace('\n',' ').replace(Regex(" +"), " ").trim()
|
||||
val font = getFont()
|
||||
advanceCursorPre(font.getWidth(str), 0)
|
||||
doc.appendDrawCall(BTeXDrawCall(typeX, typeY, inner, getSpanColour(), font, str))
|
||||
advanceCursorPost(font.getWidth(str), 0)
|
||||
val str =
|
||||
String(ch.sliceArray(start until start + length)).replace('\n', ' ').replace(Regex(" +"), " ")//.trim()
|
||||
|
||||
if (str.isNotBlank()) {
|
||||
printdbg("Characters \t\"$str\"")
|
||||
}
|
||||
}
|
||||
|
||||
private fun advanceCursorPre(w: Int, h: Int) {
|
||||
@@ -149,8 +188,99 @@ object BTeXParser {
|
||||
private val pageHeightMap = hashMapOf(
|
||||
"standard" to 25
|
||||
)
|
||||
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemBTEXDOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
if (handler.btexOpened) {
|
||||
throw BTeXParsingException("BTEXDOC tag has already opened")
|
||||
}
|
||||
|
||||
if (attribs.containsKey("def"))
|
||||
handler.def = attribs["def"]!!
|
||||
else {
|
||||
handler.cover = attribs["cover"] ?: "printout"
|
||||
handler.inner = attribs["inner"] ?: "standard"
|
||||
handler.papersize = attribs["papersize"] ?: "standard"
|
||||
|
||||
//change the "default values" of the document
|
||||
handler.pageWidth = pageWidthMap[papersize]!!
|
||||
handler.pageLines = pageHeightMap[papersize]!!
|
||||
handler.pageHeight = pageLines * LINE_HEIGHT
|
||||
|
||||
doc.pageWidth = pageWidth
|
||||
doc.pageHeight = pageHeight
|
||||
}
|
||||
|
||||
handler.btexOpened = true
|
||||
|
||||
printdbg("BTeX document: def=${handler.def}, cover=${handler.cover}, inner=${handler.inner}, papersize=${handler.papersize}, dim=${handler.pageWidth}x${handler.pageHeight} (${handler.pageLines} lines)")
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemPAIR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
if (tagStack.size == 3 && tagStack.getOrNull(1) == "blocklut") {
|
||||
blockLut[attribs["key"]!!] = attribs["value"]!!
|
||||
}
|
||||
else {
|
||||
throw BTeXParsingException("<pair> used outside of <blocklut>")
|
||||
}
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
attribs["span"]?.let {
|
||||
spanColour = it
|
||||
}
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemTABLEOFCONTENTS(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
// TODO add post-parsing hook to the handler
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemBR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemNEWPAGE(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
|
||||
}
|
||||
|
||||
@CloseTag // reflective access is impossible with 'private'
|
||||
fun closeElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
|
||||
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemARST(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@CloseTag // reflective access is impossible with 'private'
|
||||
fun closeElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
|
||||
spanColour = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private annotation class OpenTag
|
||||
private annotation class CloseTag
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user