diff --git a/lib/TerrarumSansBitmap.jar b/lib/TerrarumSansBitmap.jar index f104001f9..f07e4ec6e 100644 --- a/lib/TerrarumSansBitmap.jar +++ b/lib/TerrarumSansBitmap.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b703c12ddd334a9c2dac13bca267ab778d88696f5dc9dc5f05f0f149278fc264 -size 191902 +oid sha256:cf48385a42fc9998eae3e2daaca648823687abc7ceb6cee6610b67008b6927e8 +size 193303 diff --git a/src/net/torvald/btex/BTeXDocument.kt b/src/net/torvald/btex/BTeXDocument.kt index f2e9896dd..45d12e122 100644 --- a/src/net/torvald/btex/BTeXDocument.kt +++ b/src/net/torvald/btex/BTeXDocument.kt @@ -1,8 +1,14 @@ package net.torvald.terrarum.btex import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.OrthographicCamera +import com.badlogic.gdx.graphics.Pixmap +import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.TextureRegion +import com.badlogic.gdx.graphics.glutils.FrameBuffer +import com.badlogic.gdx.utils.Disposable +import net.torvald.terrarum.* import net.torvald.terrarum.imagefont.TinyAlphNum import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarumsansbitmap.MovableType @@ -11,7 +17,7 @@ import net.torvald.terrarumsansbitmap.gdx.CodepointSequence /** * Created by minjaesong on 2023-10-28. */ -class BTeXDocument { +class BTeXDocument : Disposable { var context = "tome" // tome (cover=hardcover), sheets (cover=typewriter or cover=printout), examination (def=examination) var font = "default" // default or typewriter var inner = "standard" @@ -42,6 +48,8 @@ class BTeXDocument { internal val pages = ArrayList() + private lateinit var pageTextures: ArrayList + val currentPage: Int get() = pages.size - 1 @@ -65,6 +73,48 @@ class BTeXDocument { linesPrintedOnPage.add(index, 0) } + /** + * Must be called on a thread with GL context! + */ + fun finalise() { + if (isFinalised) throw IllegalStateException("Page is already been finalised") + + pageTextures = ArrayList() + + val camera = OrthographicCamera(pageDimensionWidth.toFloat(), pageDimensionHeight.toFloat()) + val batch = FlippingSpriteBatch() + + pages.forEach { page -> + val fbo = FrameBuffer(Pixmap.Format.RGBA8888, pageDimensionWidth, pageDimensionHeight, false) + fbo.inAction(null, null) { + + camera.setToOrtho(false, pageDimensionWidth.toFloat(), pageDimensionHeight.toFloat()) + camera.position?.set((pageDimensionWidth / 2f).roundToFloat(), (pageDimensionHeight / 2f).roundToFloat(), 0f) // TODO floor? ceil? round? + camera.update() + batch.projectionMatrix = camera.combined + + + blendNormalStraightAlpha(batch) + batch.inUse { + page.render(0f, batch, 0, 0, pageMarginH, pageMarginV) + } + } + + pageTextures.add(TextureRegion(fbo.colorBufferTexture)) + } + isFinalised = true + + batch.dispose() + } + + override fun dispose() { + if (isFinalised) { + pageTextures.forEach { it.texture.dispose() } + } + } + + var isFinalised = false; private set + /** * Appends draw call to the list. The draw call must be prepared manually so that they would not overflow. * Use `addNewPage` to append the overflowing text to the next page. @@ -85,7 +135,12 @@ class BTeXDocument { } fun render(frameDelta: Float, batch: SpriteBatch, page: Int, x: Int, y: Int) { - pages[page].render(frameDelta, batch, x, y, pageMarginH, pageMarginV) + batch.color = Color.WHITE + + if (!isFinalised) + pages[page].render(frameDelta, batch, x, y, pageMarginH, pageMarginV) + else + batch.draw(pageTextures[page], x.toFloat(), y.toFloat()) // paint page number val num = "${page+1}" diff --git a/src/net/torvald/btex/BTeXParser.kt b/src/net/torvald/btex/BTeXParser.kt index 1701a621f..6e9d12fd0 100644 --- a/src/net/torvald/btex/BTeXParser.kt +++ b/src/net/torvald/btex/BTeXParser.kt @@ -14,6 +14,7 @@ import net.torvald.terrarum.btex.MovableTypeDrawCall import net.torvald.terrarum.ceilToFloat import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.toHex +import net.torvald.terrarum.tryDispose import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.worlddrawer.toRGBA import net.torvald.terrarumsansbitmap.MovableType @@ -42,22 +43,24 @@ object BTeXParser { operator fun invoke(file: FileHandle) = invoke(file.file()) - operator fun invoke(file: File): BTeXDocument { + operator fun invoke(file: File): Pair { val doc = BTeXDocument() val parser = SAXParserFactory.newDefaultInstance().newSAXParser() val stream = FileInputStream(file) - parser.parse(stream, BTeXHandler(doc)) - return doc + val handler = BTeXHandler(doc) + parser.parse(stream, handler) + return doc to handler } - operator fun invoke(string: String): BTeXDocument { + operator fun invoke(string: String): Pair { val doc = BTeXDocument() val parser = SAXParserFactory.newDefaultInstance().newSAXParser() - parser.parse(InputSource(StringReader(string)), BTeXHandler(doc)) - return doc + val handler = BTeXHandler(doc) + parser.parse(InputSource(StringReader(string)), handler) + return doc to handler } - internal class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() { + class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() { private val DEFAULT_FONTCOL = DEFAULT_PAGE_FORE private val LINE_HEIGHT = doc.lineHeightInPx @@ -101,6 +104,12 @@ object BTeXParser { private var hasCover = false private var coverCol: Color? = null + private lateinit var testFont: TerrarumSansBitmap + private lateinit var titleFont: TerrarumSansBitmap + private lateinit var subtitleFont: TerrarumSansBitmap + + private val bodyTextShadowAlpha = 0.36f + init { BTeXHandler::class.declaredFunctions.filter { it.findAnnotation() != null }.forEach { // println("Tag opener: ${it.name}") @@ -113,6 +122,12 @@ object BTeXParser { } } + fun dispose() { + if (::testFont.isInitialized) testFont.tryDispose() + if (::titleFont.isInitialized) titleFont.tryDispose() + if (::subtitleFont.isInitialized) subtitleFont.tryDispose() + } + private fun printdbg(message: String?) { val CSI = "\u001B[32m" val timeNow = System.currentTimeMillis() @@ -232,16 +247,10 @@ object BTeXParser { } } - private lateinit var testFont: TerrarumSansBitmap - private lateinit var titleFont: TerrarumSansBitmap - private lateinit var subtitleFont: TerrarumSansBitmap - - private val bodyTextShadowAlpha = 0.36f - private fun getFont() = when (cover) { "typewriter" -> TODO() else -> { - if (!::testFont.isInitialized) testFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha) + if (!::testFont.isInitialized) testFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha, textCacheSize = 65536) testFont } } @@ -841,7 +850,7 @@ object BTeXParser { private fun typesetBookTitle(thePar: String, handler: BTeXHandler) { val label = "\n" + thePar - typesetParagraphs(getTitleFont(), label, handler, (doc.textWidth - 16) / 2).also { + typesetParagraphs(getTitleFont(), label, handler, doc.textWidth - 16).also { val addedLines = it.sumOf { it.lineCount } doc.linesPrintedOnPage[doc.currentPage] += addedLines diff --git a/src/net/torvald/terrarum/tests/BTeXTest.kt b/src/net/torvald/terrarum/tests/BTeXTest.kt index 61bce7ba7..f553d6f9a 100644 --- a/src/net/torvald/terrarum/tests/BTeXTest.kt +++ b/src/net/torvald/terrarum/tests/BTeXTest.kt @@ -16,6 +16,7 @@ import net.torvald.terrarum.btex.BTeXDocument import net.torvald.terrarum.ceilToInt import net.torvald.terrarum.gdxClearAndEnableBlend import net.torvald.terrarum.inUse +import kotlin.system.measureTimeMillis /** @@ -24,11 +25,13 @@ import net.torvald.terrarum.inUse class BTeXTest : ApplicationAdapter() { // val filePath = "btex.xml" - val filePath = "literature/ruRU/anton_chekhov_palata_no_6.xml" + val filePath = "literature/en/daniel_defoe_robinson_crusoe.xml" +// val filePath = "literature/ruRU/anton_chekhov_palata_no_6.xml" // val filePath = "literature/koKR/yisang_nalgae.xml" private lateinit var document: BTeXDocument + private lateinit var documentHandler: BTeXParser.BTeXHandler private lateinit var batch: FlippingSpriteBatch private lateinit var camera: OrthographicCamera @@ -43,7 +46,20 @@ class BTeXTest : ApplicationAdapter() { bg = TextureRegion(Texture(Gdx.files.internal("test_assets/real_bg_with_guides.png"))) - document = BTeXParser.invoke(Gdx.files.internal("./assets/mods/basegame/books/$filePath")) + measureTimeMillis { + val f = BTeXParser.invoke(Gdx.files.internal("./assets/mods/basegame/books/$filePath")) + document = f.first + documentHandler = f.second + }.also { + println("Time spent on typesetting [ms]: $it") + } + + measureTimeMillis { + document.finalise() + documentHandler.dispose() + }.also { + println("Time spent on finalising [ms]: $it") + } } private var scroll = 0