diff --git a/.idea/artifacts/TerrarumBuild.xml b/.idea/artifacts/TerrarumBuild.xml
index 906f21916..614d8a898 100644
--- a/.idea/artifacts/TerrarumBuild.xml
+++ b/.idea/artifacts/TerrarumBuild.xml
@@ -30,13 +30,7 @@
-
-
-
-
-
-
@@ -91,6 +85,9 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/KotlinJavaRuntime.xml b/.idea/libraries/KotlinJavaRuntime.xml
index a899a6e5e..409da39e6 100644
--- a/.idea/libraries/KotlinJavaRuntime.xml
+++ b/.idea/libraries/KotlinJavaRuntime.xml
@@ -1,26 +1,23 @@
-
+
-
-
-
+
+
-
+
-
-
-
+
+
-
+
-
-
-
+
+
-
+
\ No newline at end of file
diff --git a/lib/TerrarumSansBitmap.jar b/lib/TerrarumSansBitmap.jar
index 37f803a3b..c9a0f2eab 100644
--- a/lib/TerrarumSansBitmap.jar
+++ b/lib/TerrarumSansBitmap.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:392ec047781e4fb3d2a613200996a27e0c4f23db2df351f15d3cc476350f34d1
-size 203098
+oid sha256:a51b4b41e0c1e28f49e5ccac1e6629c0d08377d5e6840581505f78d02b2fc366
+size 205412
diff --git a/src/net/torvald/btex/BTeXDocument.kt b/src/net/torvald/btex/BTeXDocument.kt
index e7379128c..eb203a4a4 100644
--- a/src/net/torvald/btex/BTeXDocument.kt
+++ b/src/net/torvald/btex/BTeXDocument.kt
@@ -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()
- private lateinit var pageTextures: ArrayList
- private lateinit var pageFrameBuffers: ArrayList
+ private lateinit var pagePixmaps: Array
+ private lateinit var pageTextures: Array
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()
+
/**
* 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
diff --git a/src/net/torvald/btex/BTeXParser.kt b/src/net/torvald/btex/BTeXParser.kt
index 2cf65467e..955ff791a 100644
--- a/src/net/torvald/btex/BTeXParser.kt
+++ b/src/net/torvald/btex/BTeXParser.kt
@@ -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() != 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
diff --git a/src/net/torvald/terrarum/imagefont/TinyAlphNum.kt b/src/net/torvald/terrarum/imagefont/TinyAlphNum.kt
index f595b2382..73eb86ab1 100644
--- a/src/net/torvald/terrarum/imagefont/TinyAlphNum.kt
+++ b/src/net/torvald/terrarum/imagefont/TinyAlphNum.kt
@@ -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()
diff --git a/src/net/torvald/terrarum/tests/BTeXTest.kt b/src/net/torvald/terrarum/tests/BTeXTest.kt
index d6529c68f..557877ba0 100644
--- a/src/net/torvald/terrarum/tests/BTeXTest.kt
+++ b/src/net/torvald/terrarum/tests/BTeXTest.kt
@@ -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)
}
diff --git a/src/net/torvald/terrarum/ui/Toolkit.kt b/src/net/torvald/terrarum/ui/Toolkit.kt
index b96397eff..fd885e778 100644
--- a/src/net/torvald/terrarum/ui/Toolkit.kt
+++ b/src/net/torvald/terrarum/ui/Toolkit.kt
@@ -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