print book without GPU

This commit is contained in:
minjaesong
2024-05-16 01:35:58 +09:00
parent 1aecfc781f
commit 7320a14a4d
8 changed files with 383 additions and 141 deletions

View File

@@ -30,13 +30,7 @@
<element id="extracted-dir" path="$PROJECT_DIR$/lib/JTransforms-3.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/JLargeArrays-1.5.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/aircompressor-0.25.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.22/kotlin-stdlib-jdk8-1.8.22.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.8.22/kotlin-stdlib-1.8.22.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.22/kotlin-stdlib-common-1.8.22.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.22/kotlin-stdlib-jdk7-1.8.22.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.8.22/kotlin-reflect-1.8.22.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test/1.8.22/kotlin-test-1.8.22.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-1.12.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-backend-lwjgl3-1.12.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.3.3.jar" path-in-jar="/" />
@@ -91,6 +85,9 @@
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-platform-1.12.1-natives-desktop.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-platform-1.12.1-natives-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/TerranVirtualDisk.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.24/kotlin-stdlib-jdk8-1.9.24.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.24/kotlin-stdlib-jdk7-1.9.24.jar" path-in-jar="/" />
</root>
</artifact>
</component>

View File

@@ -1,26 +1,23 @@
<component name="libraryTable">
<library name="KotlinJavaRuntime" type="repository">
<properties maven-id="org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22" />
<properties maven-id="org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.24" />
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.22/kotlin-stdlib-jdk8-1.8.22.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.8.22/kotlin-stdlib-1.8.22.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.22/kotlin-stdlib-common-1.8.22.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.24/kotlin-stdlib-jdk8-1.9.24.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.22/kotlin-stdlib-jdk7-1.8.22.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.24/kotlin-stdlib-jdk7-1.9.24.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.22/kotlin-stdlib-jdk8-1.8.22-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.8.22/kotlin-stdlib-1.8.22-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.22/kotlin-stdlib-common-1.8.22-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.24/kotlin-stdlib-jdk8-1.9.24-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.22/kotlin-stdlib-jdk7-1.8.22-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.24/kotlin-stdlib-jdk7-1.9.24-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.22/kotlin-stdlib-jdk8-1.8.22-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.8.22/kotlin-stdlib-1.8.22-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.22/kotlin-stdlib-common-1.8.22-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.24/kotlin-stdlib-jdk8-1.9.24-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.22/kotlin-stdlib-jdk7-1.8.22-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.24/kotlin-stdlib-jdk7-1.9.24-sources.jar!/" />
</SOURCES>
</library>
</component>

Binary file not shown.

View File

@@ -5,14 +5,15 @@ import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.*
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.FlippingSpriteBatch
import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.imagefont.TinyAlphNum
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustfile
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClustfileOutputStream
import net.torvald.terrarum.serialise.Common
import net.torvald.terrarum.tryDispose
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.utils.JsonFetcher
import net.torvald.terrarumsansbitmap.MovableType
@@ -57,6 +58,7 @@ class BTeXDocument : Disposable {
val DEFAULT_PAGE_BACK = Color(0xe0dfdb_ff.toInt())
// val DEFAULT_PAGE_FORE = Color(0x0a0706_ff)
val DEFAULT_ORNAMENTS_COL = Color(0x3f3c3b_ff)
val ccPagenum = TerrarumSansBitmap.toColorCode(0xf333)
private fun String.escape() = this.replace("\"", "\\\"")
@@ -84,7 +86,7 @@ class BTeXDocument : Disposable {
doc.inner = metaJson["inner"].asString()
doc.papersize = metaJson["papersize"].asString()
doc.fromArchive = true
doc.pageTextures = ArrayList()
doc.pageTextures = Array(pageCount) { null }
println("Title: ${doc.theTitle}")
@@ -97,7 +99,7 @@ class BTeXDocument : Disposable {
val tempFile = Gdx.files.external("./.btex-import.png") // must create new file descriptor for every page, or else every page will share a single file descriptor which cause problems
it.exportFileTo(tempFile.file())
val texture = TextureRegion(Texture(tempFile))
doc.pageTextures.add(texture)
doc.pageTextures[page] = texture
if (page == 0) {
doc.textWidth = texture.regionWidth - 2 * doc.pageMarginH
@@ -117,8 +119,8 @@ class BTeXDocument : Disposable {
internal val pages = ArrayList<BTeXPage>()
private lateinit var pageTextures: ArrayList<TextureRegion>
private lateinit var pageFrameBuffers: ArrayList<FrameBuffer>
private lateinit var pagePixmaps: Array<Pixmap?>
private lateinit var pageTextures: Array<TextureRegion?>
val currentPage: Int
get() = pages.size - 1
@@ -143,53 +145,44 @@ class BTeXDocument : Disposable {
linesPrintedOnPage.add(index, 0)
}
private val lock = Any()
private val texturefiedPages = HashSet<Int>()
/**
* Must be called on a thread with GL context!
*/
fun finalise() {
if (fromArchive) throw IllegalStateException("Document is loaded from the archive and thus cannot be finalised")
if (isFinalised) throw IllegalStateException("Page is already been finalised")
fun finalise(multithread: Boolean = false) {
synchronized(lock) {
if (fromArchive) throw IllegalStateException("Document is loaded from the archive and thus cannot be finalised")
if (isFinalised) throw IllegalStateException("Page is already been finalised")
// TODO serialise and finalise via CPU (store every page as Pixmap)
// serialise and finalise via CPU (store every page as Pixmap)
pageTextures = ArrayList()
pageFrameBuffers = ArrayList()
pageTextures = Array(pages.size) { null }
pagePixmaps = Array(pages.size) { null }
val camera = OrthographicCamera(pageDimensionWidth.toFloat(), pageDimensionHeight.toFloat())
val batch = FlippingSpriteBatch()
pages.forEachIndexed { pageNum, 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)
printPageNumber(batch, pageNum, 0, 0)
pages.forEachIndexed { pageNum, page ->
val pixmap = Pixmap(pageDimensionWidth, pageDimensionHeight, Pixmap.Format.RGBA8888).also {
it.blending = Pixmap.Blending.SourceOver
it.filter = Pixmap.Filter.NearestNeighbour
}
page.renderToPixmap(pixmap, 0, 0, pageMarginH, pageMarginV)
printPageNumber(pixmap, pageNum, 0, 0)
pagePixmaps[pageNum] = pixmap
}
pageTextures.add(TextureRegion(fbo.colorBufferTexture))
pageFrameBuffers.add(fbo)
isFinalised = true
}
isFinalised = true
batch.dispose()
}
override fun dispose() {
if (isFinalised) {
pageTextures.forEach { it.texture.dispose() }
pageFrameBuffers.forEach { it.dispose() }
pageTextures.forEach { it?.texture?.dispose() }
pagePixmaps.forEach { it?.tryDispose() }
}
else if (fromArchive) {
pageTextures.forEach { it.texture.dispose() }
pageTextures.forEach { it?.texture?.dispose() }
pagePixmaps.forEach { it?.tryDispose() }
}
}
@@ -218,13 +211,9 @@ class BTeXDocument : Disposable {
it.writeBytes(json.encodeToByteArray())
}
pageFrameBuffers.forEachIndexed { index, fbo ->
val file = Clustfile(DOM, "$index.png").also {
it.createNewFile()
}
fbo.inAction(null, null) {
val pixmap = Pixmap.createFromFrameBuffer(0, 0, fbo.width, fbo.height)
pagePixmaps.forEachIndexed { index, pixmap ->
Clustfile(DOM, "$index.png").also { file ->
file.createNewFile()
val tempFile = Gdx.files.external("./.btex-export.png")
PixmapIO.writePNG(tempFile, pixmap, Deflater.BEST_COMPRESSION, false)
val outstream = ClustfileOutputStream(file)
@@ -262,8 +251,13 @@ class BTeXDocument : Disposable {
fun render(frameDelta: Float, batch: SpriteBatch, page: Int, x: Int, y: Int) {
batch.color = Color.WHITE
if (isFinalised || fromArchive)
if (fromArchive || isFinalised && texturefiedPages.contains(page))
batch.draw(pageTextures[page], x.toFloat(), y.toFloat())
else if (isFinalised && !texturefiedPages.contains(page)) {
pageTextures[page] = TextureRegion(Texture(pagePixmaps[page]))
texturefiedPages.add(page)
batch.draw(pageTextures[page], x.toFloat(), y.toFloat())
}
else {
pages[page].render(frameDelta, batch, x, y, pageMarginH, pageMarginV)
printPageNumber(batch, page, x, y)
@@ -289,6 +283,26 @@ class BTeXDocument : Disposable {
TinyAlphNum.draw(batch, num, numX.toFloat(), numY.toFloat())
}
}
private fun printPageNumber(pixmap: Pixmap, page: Int, x: Int, y: Int) {
val num = "${page + 1}"
val numW = TinyAlphNum.getWidth(num)
val numX = if (context == "tome") {
if (page % 2 == 1)
x + pageMarginH
else
x + pageDimensionWidth - pageMarginH - numW
}
else {
x + (pageDimensionWidth - numW) / 2
}
val numY = y + pageDimensionHeight - 2 * pageMarginV - 4
if (page == 0 && context != "tome" || page in tocPageStart until endOfPageStart) {
pixmap.setColor(DEFAULT_ORNAMENTS_COL)
TinyAlphNum.drawToPixmap(pixmap, "$ccPagenum$num", numX, numY)
}
}
}
class BTeXPage(
@@ -320,6 +334,18 @@ class BTeXPage(
fun isEmpty() = drawCalls.isEmpty()
fun isNotEmpty() = drawCalls.isNotEmpty()
fun renderToPixmap(pixmap: Pixmap, x: Int, y: Int, marginH: Int, marginV: Int) {
drawCalls.sortedBy { if (it.text != null) 16 else 0 }.let { drawCalls ->
val backCol = back.cpy().also { it.a = 0.93f }
pixmap.setColor(backCol)
pixmap.fill()
pixmap.setColor(Color.WHITE)
drawCalls.forEach {
it.drawToPixmap(pixmap, x + marginH, y + marginV)
}
}
}
}
@@ -328,6 +354,10 @@ data class TypesetDrawCall(val movableType: MovableType, val rowStart: Int, val
fun draw(doc: BTeXDocument, batch: SpriteBatch, x: Float, y: Float) {
movableType.draw(batch, x, y, rowStart, minOf(rows, doc.pageLines))
}
fun drawToPixmap(doc: BTeXDocument, pixmap: Pixmap, x: Int, y: Int) {
movableType.drawToPixmap(pixmap, x, y, rowStart, minOf(rows, doc.pageLines))
}
}
abstract class BTeXBatchDrawCall(
@@ -336,6 +366,7 @@ abstract class BTeXBatchDrawCall(
val parentText: BTeXDrawCall?// = null
) {
abstract fun draw(doc: BTeXDocument, batch: SpriteBatch, x: Float, y: Float, font: TerrarumSansBitmap? = null)
abstract fun drawToPixmap(doc: BTeXDocument, pixmap: Pixmap, x: Int, y: Int, font: TerrarumSansBitmap? = null)
}
class BTeXDrawCall(
@@ -359,11 +390,6 @@ class BTeXDrawCall(
val px = (posX + x).toFloat()
val py = (posY + y).toFloat()
if (theme == "code") {
// todo draw code background
println("code themed")
}
extraDrawFun(batch, px, py)
batch.color = Color.WHITE
@@ -384,6 +410,23 @@ class BTeXDrawCall(
return true
}
fun drawToPixmap(pixmap: Pixmap, x: Int, y: Int) {
val px = posX + x
val py = posY + y
extraPixmapDrawFun(pixmap, px, py)
pixmap.setColor(Color.WHITE)
if (text != null && cmd == null) {
text.drawToPixmap(doc, pixmap, px, py)
}
else if (text == null && cmd != null) {
cmd.drawToPixmap(doc, pixmap, px, py, font)
}
else throw Error("Text and Texture are both non-null")
}
internal val width: Int
get() = if (text != null)
text.movableType.width * text.movableType.font.scale
@@ -391,6 +434,7 @@ class BTeXDrawCall(
cmd!!.width
internal var extraDrawFun: (SpriteBatch, Float, Float) -> Unit = { _, _, _ ->}
internal var extraPixmapDrawFun: (Pixmap, Int, Int) -> Unit = { _, _, _ ->}
internal val lineCount = if (text != null)
text.rows
else

View File

@@ -2,7 +2,9 @@ package net.torvald.btex
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.Disposable
import com.jme3.math.FastMath.DEG_TO_RAD
import net.torvald.colourutil.OKLch
import net.torvald.colourutil.tosRGB
@@ -121,13 +123,6 @@ object BTeXParser {
private var hasCover = false
private var coverCol: Color? = null
private lateinit var testFont: TerrarumSansBitmap
private lateinit var partTitleFont: TerrarumSansBitmap
private lateinit var titleFont: TerrarumSansBitmap
private lateinit var subtitleFont: TerrarumSansBitmap
private val bodyTextShadowAlpha = 0.36f
private val macrodefs = hashMapOf(
"thepart" to "Part %1\$s",
"parttype" to "I",
@@ -158,6 +153,10 @@ object BTeXParser {
}
init {
if (!fontInit) {
throw RuntimeException("Font not initialised: call BTeXParser.BTeXHandler.preloadFonts() WITHIN OpenGL-context thread to initialise the fonts.")
}
BTeXHandler::class.declaredFunctions.filter { it.findAnnotation<OpenTag>() != null }.forEach {
// println("Tag opener: ${it.name}")
elemOpeners[it.name] = it
@@ -179,6 +178,14 @@ object BTeXParser {
font.draw(batch, "${ccDefault}E", x + (15 + 2*interchar)*scale, y + 4*scale)
font.draw(batch, "${ccDefault}X", x + (23 + 3*interchar)*scale, y + 0*scale)
}
override fun drawToPixmap(doc: BTeXDocument, pixmap: Pixmap, x: Int, y: Int, font: TerrarumSansBitmap?) {
val scale = font!!.scale
val interchar = font.interchar
font.drawToPixmap(pixmap, "${ccDefault}B", x + ( 0 + 0*interchar)*scale, y + 0*scale)
font.drawToPixmap(pixmap, "${ccDefault}T", x + ( 8 + 1*interchar)*scale, y + 0*scale)
font.drawToPixmap(pixmap, "${ccDefault}E", x + (15 + 2*interchar)*scale, y + 4*scale)
font.drawToPixmap(pixmap, "${ccDefault}X", x + (23 + 3*interchar)*scale, y + 0*scale)
}
}
}
@@ -194,6 +201,15 @@ object BTeXParser {
font.draw(batch, "${ccDefault}E", x + (19 + 2 * interchar) * scale, y + 4 * scale)
font.draw(batch, "${ccDefault}X", x + (27 + 3 * interchar) * scale, y + 0 * scale)
}
override fun drawToPixmap(doc: BTeXDocument, pixmap: Pixmap, x: Int, y: Int, font: TerrarumSansBitmap?) {
val scale = font!!.scale
val interchar = font.interchar
font.drawToPixmap(pixmap, "${ccDefault}L", x + (0 + 0 * interchar) * scale, y + 0 * scale)
font.drawToPixmap(pixmap, "${ccDefault}", x + (4 + 0 * interchar) * scale, y + -4 * scale)
font.drawToPixmap(pixmap, "${ccDefault}T", x + (12 + 1 * interchar) * scale, y + 0 * scale)
font.drawToPixmap(pixmap, "${ccDefault}E", x + (19 + 2 * interchar) * scale, y + 4 * scale)
font.drawToPixmap(pixmap, "${ccDefault}X", x + (27 + 3 * interchar) * scale, y + 0 * scale)
}
}
}
@@ -207,17 +223,17 @@ object BTeXParser {
font.draw(batch, "${ccDefault}E", x + (7 + 2 * interchar) * scale, y + 4 * scale)
font.draw(batch, "${ccDefault}X", x + (15 + 3 * interchar) * scale, y + 0 * scale)
}
override fun drawToPixmap(doc: BTeXDocument, pixmap: Pixmap, x: Int, y: Int, font: TerrarumSansBitmap?) {
val scale = font!!.scale
val interchar = font.interchar
font.drawToPixmap(pixmap, "${ccDefault}T", x + (0 + 1 * interchar) * scale, y + 0 * scale)
font.drawToPixmap(pixmap, "${ccDefault}E", x + (7 + 2 * interchar) * scale, y + 4 * scale)
font.drawToPixmap(pixmap, "${ccDefault}X", x + (15 + 3 * interchar) * scale, y + 0 * scale)
}
}
}
}
fun dispose() {
if (::testFont.isInitialized) testFont.tryDispose()
if (::titleFont.isInitialized) titleFont.tryDispose()
if (::partTitleFont.isInitialized) partTitleFont.tryDispose()
if (::subtitleFont.isInitialized) subtitleFont.tryDispose()
}
override fun warning(e: SAXParseException) {
e.printStackTrace()
}
@@ -357,31 +373,18 @@ object BTeXParser {
private fun getFont() = when (cover) {
"typewriter" -> TODO()
else -> {
if (!::testFont.isInitialized) testFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha, textCacheSize = 4096)
testFont
}
else -> testFont
}
private fun getPartTitleFont(): TerrarumSansBitmap {
if (!::partTitleFont.isInitialized) partTitleFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha).also {
it.interchar = 1
}
return partTitleFont
}
private fun getTitleFont(): TerrarumSansBitmap {
if (!::titleFont.isInitialized) titleFont = TerrarumSansBitmap(App.FONT_DIR).also {
it.interchar = 1
it.scale = 2
}
return titleFont
}
private fun getSubtitleFont(): TerrarumSansBitmap {
if (!::subtitleFont.isInitialized) subtitleFont = TerrarumSansBitmap(App.FONT_DIR).also {
it.interchar = 1
}
return subtitleFont
}
@@ -1020,6 +1023,27 @@ object BTeXParser {
batch.color = oldcol
}
}
it.extraPixmapDrawFun = { pixmap, x, y ->
val width = doc.textWidth - 2 * MARGIN_PARBOX_H
val height = it.lineCount * doc.lineHeightInPx
if (height > 0) {
pixmap.setColor(Color(0xccccccff.toInt()))
pixmap.fillRectangle(
x - MARGIN_PARBOX_H,
y - MARGIN_PARBOX_V,
width + 2 * MARGIN_PARBOX_H,
height + 2 * MARGIN_PARBOX_V
)
pixmap.setColor(Color(0x999999ff.toInt()))
Toolkit.drawBoxBorderToPixmap(pixmap,
x - MARGIN_PARBOX_H,
y - MARGIN_PARBOX_V,
width + 2 * MARGIN_PARBOX_H,
height + 2 * MARGIN_PARBOX_V
)
}
}
}
insertOneEmptyLineOrAddNewPage()
@@ -1291,6 +1315,15 @@ object BTeXParser {
batch.color = Color.WHITE
Toolkit.fillArea(batch, px, py, pw, 1f)
}
it.last().extraPixmapDrawFun = { pixmap, x, y ->
val px = x
val py = y + doc.lineHeightInPx - 1
val pw = doc.textWidth - 2 * MARGIN_TITLE_TEXTS
pixmap.setColor(Color(1f,1f,1f,.5f))
pixmap.fillRectangle(px, py, pw+1, 2)
pixmap.setColor(Color.WHITE)
pixmap.fillRectangle(px, py, pw, 1)
}
it.forEach {
it.posX += MARGIN_TITLE_TEXTS
@@ -1389,6 +1422,22 @@ object BTeXParser {
)
batch.color = oldCol
}
it.extraPixmapDrawFun = { pixmap, x, y ->
pixmap.setColor(DEFAULT_ORNAMENTS_COL.cpy().also { it.a *= bodyTextShadowAlpha })
pixmap.fillRectangle(
x - (indent - 2),
y + doc.lineHeightInPx,
7,
1 + (it.lineCount - 1).coerceAtLeast(1) * doc.lineHeightInPx
)
pixmap.setColor(DEFAULT_ORNAMENTS_COL)
pixmap.fillRectangle(
x - (indent - 2),
y + doc.lineHeightInPx,
6,
(it.lineCount - 1).coerceAtLeast(1) * doc.lineHeightInPx
)
}
}
}
}
@@ -1601,11 +1650,25 @@ object BTeXParser {
font.draw(batch, pageNum, x + typeWidth - pageNumWidth.toFloat(), y)
batch.color = oldCol
// println("pos: ($x, $y)\tTOC: $name -- dot start: ${(x + textWidth).div(dotGap).ceilToFloat() * dotGap}, dot end: $dotCursor, typeWidth=$typeWidth, pageNumWidth=$pageNumWidth")
}
call.extraPixmapDrawFun = { pixmap, x, y ->
val font = getFont()
val y = y + (call.lineCount - 1).coerceAtLeast(0) * doc.lineHeightInPx
val textWidth = if (call.text is TypesetDrawCall) {
font.getWidthNormalised(call.text.movableType.typesettedSlugs.last())
}
else call.width
var dotCursor = (x.toFloat() + textWidth).div(dotGap).ceilToInt() * dotGap
while (dotCursor < x + dotPosEnd) {
font.drawToPixmap(pixmap, "$ccDefault·", dotCursor + dotGap/2, y)
dotCursor += dotGap
}
font.drawToPixmap(pixmap, "$ccDefault$pageNum", x + typeWidth - pageNumWidth, y)
}
}
}
}
@@ -1619,10 +1682,44 @@ object BTeXParser {
companion object {
init {
App.disposables.add(object : Disposable {
override fun dispose() {
testFont.dispose()
partTitleFont.dispose()
titleFont.dispose()
subtitleFont.dispose()
}
})
}
private val siblingAwareTags = arrayOf(
"PART","CHAPTER","SECTION","SUBSECTION","P","I","LI"
)
private val bodyTextShadowAlpha = 0.36f
private var fontInit = false
private lateinit var testFont: TerrarumSansBitmap
private lateinit var partTitleFont: TerrarumSansBitmap
private lateinit var titleFont: TerrarumSansBitmap
private lateinit var subtitleFont: TerrarumSansBitmap
fun preloadFonts() {
testFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha, textCacheSize = 4096)
partTitleFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha).also {
it.interchar = 1
}
titleFont = TerrarumSansBitmap(App.FONT_DIR).also {
it.interchar = 1
it.scale = 2
}
subtitleFont = TerrarumSansBitmap(App.FONT_DIR).also {
it.interchar = 1
}
fontInit = true
}
private const val MARGIN_PARBOX_V = 4
private const val MARGIN_PARBOX_H = 12
private const val MARGIN_TITLE_TEXTS = 8

View File

@@ -1,11 +1,14 @@
package net.torvald.terrarum.imagefont
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.GlyphLayout
import net.torvald.terrarum.roundToFloat
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import kotlin.math.roundToInt
/**
* Created by minjaesong on 2016-04-15.
@@ -16,13 +19,18 @@ object TinyAlphNum : BitmapFont() {
internal const val H = 13
internal val fontSheet = TextureRegionPack("./assets/graphics/fonts/7x13_Tamzen7x14b.tga", W+1, H+1)
internal val fontPixmap = Pixmap(Gdx.files.internal("./assets/graphics/fonts/7x13_Tamzen7x14b.tga"))
init {
setOwnsTexture(true)
setUseIntegerPositions(true)
}
override fun dispose() {
fontSheet.dispose()
fontPixmap.dispose()
}
fun getWidth(str: String): Int {
var l = 0
for (char in str) {
@@ -33,7 +41,8 @@ object TinyAlphNum : BitmapFont() {
return W * l
}
lateinit var colMain: Color
private var colMain = Color.WHITE
private var colMainInt = -1
override fun draw(batch: Batch, text: CharSequence, x: Float, y: Float): GlyphLayout? {
val originalColour = batch.color.cpy()
@@ -65,6 +74,79 @@ object TinyAlphNum : BitmapFont() {
return null
}
fun drawToPixmap(pixmap: Pixmap, text: String, x: Int, y: Int) {
var charsPrinted = 0
text.forEachIndexed { index, c ->
if (isColourCodeHigh(c)) {
val cchigh = c
val cclow = text[index + 1]
val colour = getColour(cchigh, cclow)
colMainInt = colour.toRGBA8888()
}
else if (c in 0.toChar()..255.toChar()) {
val srcX = (c.code % 16) * (W+1)
val srcY = (c.code / 16) * (H+1)
val destX = x + charsPrinted * W
val destY = y
pixmap.drawPixmap(fontPixmap, srcX, srcY, W+1, H+1, destX, destY, colMainInt)
charsPrinted += 1
}
}
}
/***
* @param col RGBA8888 representation
*/
private fun Pixmap.drawPixmap(pixmap: Pixmap, srcX: Int, srcY: Int, srcW: Int, srcH: Int, destX: Int, destY: Int, col: Int) {
for (y in srcY until srcY + srcH) {
for (x in srcX until srcX + srcW) {
val pixel = pixmap.getPixel(x, y)
val newPixel = pixel colorTimes col
this.drawPixel(destX + x - srcX, destY + y - srcY, newPixel)
}
}
}
private fun Color.toRGBA8888() =
(this.r * 255f).toInt().shl(24) or
(this.g * 255f).toInt().shl(16) or
(this.b * 255f).toInt().shl(8) or
(this.a * 255f).toInt()
/**
* RGBA8888 representation
*/
private fun Int.forceOpaque() = this.and(0xFFFFFF00.toInt()) or 0xFF
private infix fun Int.colorTimes(other: Int): Int {
val thisBytes = IntArray(4) { this.ushr(it * 8).and(255) }
val otherBytes = IntArray(4) { other.ushr(it * 8).and(255) }
return (thisBytes[0] times256 otherBytes[0]) or
(thisBytes[1] times256 otherBytes[1]).shl(8) or
(thisBytes[2] times256 otherBytes[2]).shl(16) or
(thisBytes[3] times256 otherBytes[3]).shl(24)
}
private infix fun Int.times256(other: Int) = multTable255[this][other]
private val multTable255 = Array(256) { left ->
IntArray(256) { right ->
(255f * (left / 255f).times(right / 255f)).roundToInt()
}
}
override fun getLineHeight() = H.toFloat()
override fun getCapHeight() = getLineHeight()
override fun getXHeight() = getLineHeight()

View File

@@ -13,7 +13,9 @@ import com.badlogic.gdx.graphics.glutils.ShaderProgram
import net.torvald.btex.BTeXParser
import net.torvald.terrarum.*
import net.torvald.terrarum.btex.BTeXDocument
import net.torvald.terrarum.imagefont.TinyAlphNum
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.ui.Toolkit
import net.torvald.unicode.EMDASH
import java.io.File
import kotlin.system.measureTimeMillis
@@ -44,7 +46,10 @@ class BTeXTest : ApplicationAdapter() {
)
override fun create() {
Lang.invoke()
Lang
TinyAlphNum
Toolkit
BTeXParser.BTeXHandler.preloadFonts()
batch = FlippingSpriteBatch(1000)
camera = OrthographicCamera(1280f, 720f)
@@ -57,26 +62,27 @@ class BTeXTest : ApplicationAdapter() {
val isBookFinalised = filePath.endsWith(".btxbook")
if (!isBookFinalised) {
measureTimeMillis {
val f = BTeXParser.invoke(Gdx.files.internal("./assets/mods/basegame/books/$filePath"), varMap)
document = f.first
documentHandler = f.second
}.also {
println("Time spent on typesetting [ms]: $it")
}
Thread {
measureTimeMillis {
val f = BTeXParser.invoke(Gdx.files.internal("./assets/mods/basegame/books/$filePath"), varMap)
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")
}
measureTimeMillis {
document.finalise()
}.also {
println("Time spent on finalising [ms]: $it")
}
measureTimeMillis {
/*measureTimeMillis {
document.serialise(File("./assets/mods/basegame/books/${filePath.replace(".xml", ".btxbook")}"))
}.also {
println("Time spent on serialisation [ms]: $it")
}*/
}.also {
println("Time spent on serialisation [ms]: $it")
}*/
}.start()
}
else {
measureTimeMillis {
@@ -96,28 +102,35 @@ class BTeXTest : ApplicationAdapter() {
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
val drawX = (1280 - (pageGap + document.pageDimensionWidth*2)) / 2
val drawY = 24
if (::document.isInitialized) {
if (document.isFinalised) {
val drawX = (1280 - (pageGap + document.pageDimensionWidth * 2)) / 2
val drawY = 24
batch.inUse {
batch.color = Color.WHITE
batch.draw(bg, 0f, 0f)
batch.inUse {
batch.color = Color.WHITE
batch.draw(bg, 0f, 0f)
if (scroll - 1 in document.pageIndices)
document.render(0f, batch, scroll - 1, drawX, drawY)
if (scroll in document.pageIndices)
document.render(0f, batch, scroll, drawX + (6 + document.pageDimensionWidth), drawY)
if (scroll - 1 in document.pageIndices)
document.render(0f, batch, scroll - 1, drawX, drawY)
if (scroll in document.pageIndices)
document.render(0f, batch, scroll, drawX + (6 + document.pageDimensionWidth), drawY)
}
if (Gdx.input.isKeyJustPressed(Input.Keys.LEFT))
scroll = (scroll - 2).coerceAtLeast(0)
else if (Gdx.input.isKeyJustPressed(Input.Keys.RIGHT))
scroll =
(scroll + 2).coerceAtMost(
document.pageIndices.endInclusive.toFloat().div(2f).ceilToInt().times(2)
)
else if (Gdx.input.isKeyJustPressed(Input.Keys.PAGE_UP))
scroll = 0
else if (Gdx.input.isKeyJustPressed(Input.Keys.PAGE_DOWN))
scroll = document.pageIndices.endInclusive.toFloat().div(2f).ceilToInt().times(2)
}
}
if (Gdx.input.isKeyJustPressed(Input.Keys.LEFT))
scroll = (scroll - 2).coerceAtLeast(0)
else if (Gdx.input.isKeyJustPressed(Input.Keys.RIGHT))
scroll = (scroll + 2).coerceAtMost(document.pageIndices.endInclusive.toFloat().div(2f).ceilToInt().times(2))
else if (Gdx.input.isKeyJustPressed(Input.Keys.PAGE_UP))
scroll = 0
else if (Gdx.input.isKeyJustPressed(Input.Keys.PAGE_DOWN))
scroll = document.pageIndices.endInclusive.toFloat().div(2f).ceilToInt().times(2)
}

View File

@@ -188,6 +188,18 @@ object Toolkit : Disposable {
}
// draws highly simplified box border
fun drawBoxBorderToPixmap(pixmap: Pixmap, x: Int, y: Int, w: Int, h: Int) {
// top edge
pixmap.fillRectangle(x, y - 1, w, 1)
// bottom edge
pixmap.fillRectangle(x, y + h, w, 1)
// left edge
pixmap.fillRectangle(x - 1, y, 1, h)
// right edge
pixmap.fillRectangle(x + w, y, 1, h)
}
private lateinit var blurtex0: Texture
private lateinit var blurtex1: Texture
private lateinit var blurtex2: Texture