mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
progress indicator for the tester
This commit is contained in:
@@ -26,6 +26,7 @@ import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
||||
import java.io.File
|
||||
import java.io.RandomAccessFile
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.zip.Deflater
|
||||
|
||||
/**
|
||||
@@ -149,14 +150,16 @@ class BTeXDocument : Disposable {
|
||||
|
||||
@Transient private val fontNum = TinyAlphNum
|
||||
|
||||
fun addNewPage(back: Color = DEFAULT_PAGE_BACK) {
|
||||
fun addNewPage(progressIndicator: AtomicInteger, back: Color = DEFAULT_PAGE_BACK) {
|
||||
pages.add(BTeXPage(this, back, pageDimensionWidth, pageDimensionHeight))
|
||||
linesPrintedOnPage.add(0)
|
||||
progressIndicator.getAndAdd(1)
|
||||
}
|
||||
|
||||
fun addNewPageAt(index: Int, back: Color = DEFAULT_PAGE_BACK) {
|
||||
fun addNewPageAt(progressIndicator: AtomicInteger, index: Int, back: Color = DEFAULT_PAGE_BACK) {
|
||||
pages.add(index, BTeXPage(this, back, pageDimensionWidth, pageDimensionHeight))
|
||||
linesPrintedOnPage.add(index, 0)
|
||||
progressIndicator.getAndAdd(1)
|
||||
}
|
||||
|
||||
private val lock = Any()
|
||||
@@ -165,7 +168,7 @@ class BTeXDocument : Disposable {
|
||||
/**
|
||||
* Must be called on a thread with GL context!
|
||||
*/
|
||||
fun finalise(multithread: Boolean = false) {
|
||||
fun finalise(progressIndicator: AtomicInteger, 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")
|
||||
@@ -184,6 +187,7 @@ class BTeXDocument : Disposable {
|
||||
page.renderToPixmap(pixmap, 0, 0, pageMarginH, pageMarginV)
|
||||
printPageNumber(pixmap, pageNum, 0, 0)
|
||||
pagePixmaps[pageNum] = pixmap
|
||||
progressIndicator.getAndAdd(1)
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -196,6 +200,8 @@ class BTeXDocument : Disposable {
|
||||
page.renderToPixmap(pixmap, 0, 0, pageMarginH, pageMarginV)
|
||||
printPageNumber(pixmap, pageNum, 0, 0)
|
||||
pagePixmaps[pageNum] = pixmap
|
||||
progressIndicator.getAndAdd(1)
|
||||
Unit
|
||||
} }
|
||||
|
||||
// my experiment tells 4, 8, 16, 32 threads all perform the same
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.xml.sax.helpers.DefaultHandler
|
||||
import java.awt.SystemColor.text
|
||||
import java.io.*
|
||||
import java.net.URL
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import javax.xml.parsers.SAXParserFactory
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.reflect.KFunction
|
||||
@@ -46,9 +47,9 @@ object BTeXParser {
|
||||
internal val textTags = hashSetOf("P", "CALLOUT", "TITLE", "AUTHOR", "EDITION", "CHAPTER", "SECTION", "LI")
|
||||
internal val textDecorTags = hashSetOf("SPAN", "CODE")
|
||||
|
||||
operator fun invoke(file: FileHandle, varMap: Map<String, String>) = invoke(file.file(), varMap)
|
||||
operator fun invoke(file: FileHandle, varMap: Map<String, String>, progressIndicator: AtomicInteger) = invoke(file.file(), varMap, progressIndicator)
|
||||
|
||||
operator fun invoke(file: File, varMap: Map<String, String>): Pair<BTeXDocument, BTeXHandler> {
|
||||
operator fun invoke(file: File, varMap: Map<String, String>, progressIndicator: AtomicInteger): Pair<BTeXDocument, BTeXHandler> {
|
||||
val doc = BTeXDocument()
|
||||
val parser = SAXParserFactory.newInstance().let {
|
||||
it.isNamespaceAware = true
|
||||
@@ -56,24 +57,24 @@ object BTeXParser {
|
||||
it.newSAXParser()
|
||||
}
|
||||
val stream = FileInputStream(file)
|
||||
val handler = BTeXHandler(doc, varMap)
|
||||
val handler = BTeXHandler(doc, varMap, progressIndicator)
|
||||
parser.parse(stream, handler)
|
||||
return doc to handler
|
||||
}
|
||||
|
||||
operator fun invoke(string: String, varMap: Map<String, String>): Pair<BTeXDocument, BTeXHandler> {
|
||||
operator fun invoke(string: String, varMap: Map<String, String>, progressIndicator: AtomicInteger): Pair<BTeXDocument, BTeXHandler> {
|
||||
val doc = BTeXDocument()
|
||||
val parser = SAXParserFactory.newInstance().let {
|
||||
it.isNamespaceAware = true
|
||||
it.isValidating = true
|
||||
it.newSAXParser()
|
||||
}
|
||||
val handler = BTeXHandler(doc, varMap)
|
||||
val handler = BTeXHandler(doc, varMap, progressIndicator)
|
||||
parser.parse(InputSource(StringReader(string)), handler)
|
||||
return doc to handler
|
||||
}
|
||||
|
||||
class BTeXHandler(val doc: BTeXDocument, val varMap: Map<String, String>) : DefaultHandler() {
|
||||
class BTeXHandler(val doc: BTeXDocument, val varMap: Map<String, String>, val progressIndicator: AtomicInteger) : DefaultHandler() {
|
||||
private var cover = ""
|
||||
private var inner = ""
|
||||
private var papersize = ""
|
||||
@@ -787,19 +788,19 @@ object BTeXParser {
|
||||
val coverColLCH = OKLch(hue, 0.05f, 0.36f)
|
||||
val (r, g, b) = coverColLCH.tosRGB()
|
||||
coverCol = Color(r, g, b, 1f)
|
||||
doc.addNewPage(coverCol!!)
|
||||
doc.addNewPage(progressIndicator, coverCol!!)
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemTOCPAGE(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) {
|
||||
doc.addNewPage() // toc: openright
|
||||
doc.addNewPage(progressIndicator) // toc: openright
|
||||
val header = attribs["title"] ?: "Table of Contents"
|
||||
typesetChapterHeading(null, header, handler, PAR_INDENTATION)
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemINDEXPAGE(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) {
|
||||
if (doc.currentPageObj.isNotEmpty()) doc.addNewPage()
|
||||
if (doc.currentPageObj.isNotEmpty()) doc.addNewPage(progressIndicator)
|
||||
val header = attribs["title"] ?: "Index"
|
||||
typesetChapterHeading(null, header, handler, PAR_INDENTATION)
|
||||
}
|
||||
@@ -828,7 +829,7 @@ object BTeXParser {
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemMANUSCRIPT(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) {
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
}
|
||||
|
||||
@CloseTag
|
||||
@@ -854,7 +855,7 @@ object BTeXParser {
|
||||
|
||||
// insert new pages
|
||||
repeat(pageDelta) {
|
||||
doc.addNewPageAt(tocPage!! + 1)
|
||||
doc.addNewPageAt(progressIndicator, tocPage!! + 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -979,7 +980,7 @@ object BTeXParser {
|
||||
|
||||
// image overflowing?
|
||||
if (doc.pageLines - doc.linesPrintedOnPage.last() < heightInLines)
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
|
||||
val tempFile = FileHandle.tempFile("btex_$btexObjName")
|
||||
try {
|
||||
@@ -1059,7 +1060,7 @@ object BTeXParser {
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
fun processElemNEWPAGE(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) {
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
}
|
||||
|
||||
@CloseTag // reflective access is impossible with 'private'
|
||||
@@ -1085,7 +1086,7 @@ object BTeXParser {
|
||||
}
|
||||
}
|
||||
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
}
|
||||
|
||||
@OpenTag // reflective access is impossible with 'private'
|
||||
@@ -1237,7 +1238,7 @@ object BTeXParser {
|
||||
@CloseTag
|
||||
fun closeElemCOVER(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) {
|
||||
if (hasCover) {
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1305,7 +1306,7 @@ object BTeXParser {
|
||||
@CloseTag // reflective access is impossible with 'private'
|
||||
fun closeElemPART(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) {
|
||||
// if the last page is not empty, create new one
|
||||
if (doc.currentPageObj.isNotEmpty()) doc.addNewPage()
|
||||
if (doc.currentPageObj.isNotEmpty()) doc.addNewPage(progressIndicator)
|
||||
|
||||
val partOrder = cptSectMap.count { it.type.startsWith("part") } + 1
|
||||
val thePar = paragraphBuffer.toString().trim()
|
||||
@@ -1343,10 +1344,10 @@ object BTeXParser {
|
||||
|
||||
|
||||
// if current line is the last line, proceed to the next page
|
||||
if (doc.linesPrintedOnPage.last() >= doc.pageLines - 2) doc.addNewPage()
|
||||
if (doc.linesPrintedOnPage.last() >= doc.pageLines - 2) doc.addNewPage(progressIndicator)
|
||||
// if defined by the macro, proceed to the next page
|
||||
if (macrodefs["chapteronnewpage"] != "0" && cptSibling > 1)
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
|
||||
|
||||
typesetChapterHeading(invokeMacro("thechapter", cptNumStr), thePar, handler, 16)
|
||||
@@ -1358,7 +1359,7 @@ object BTeXParser {
|
||||
@CloseTag // reflective access is impossible with 'private'
|
||||
fun closeElemSECTION(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) {
|
||||
// if current line is the last line, proceed to the next page
|
||||
if (doc.linesPrintedOnPage.last() >= doc.pageLines - 1) doc.addNewPage()
|
||||
if (doc.linesPrintedOnPage.last() >= doc.pageLines - 1) doc.addNewPage(progressIndicator)
|
||||
|
||||
val partOrder = cptSectMap.count { it.type.startsWith("part") }
|
||||
val cptOrder = cptSectMap.count { it.type.startsWith("chapter") }
|
||||
@@ -1421,8 +1422,8 @@ object BTeXParser {
|
||||
fun closeElemBTEXDOC(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) {
|
||||
// make sure the last pair ends with paper and end-cover
|
||||
doc.endOfPageStart = doc.currentPage + 1
|
||||
if (doc.pages.size % 2 == 1) doc.addNewPage()
|
||||
doc.addNewPage()
|
||||
if (doc.pages.size % 2 == 1) doc.addNewPage(progressIndicator)
|
||||
doc.addNewPage(progressIndicator)
|
||||
}
|
||||
|
||||
|
||||
@@ -1523,9 +1524,9 @@ object BTeXParser {
|
||||
|
||||
// make sure page after the part always openright
|
||||
if (doc.currentPage % 2 == 1)
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
}
|
||||
|
||||
private fun typesetChapterHeading(num: String?, thePar: String, handler: BTeXHandler, indent: Int = 16, width: Int = doc.textWidth) {
|
||||
@@ -1622,7 +1623,7 @@ object BTeXParser {
|
||||
// printdbg("Page: ${doc.currentPage+1}, Line: ${doc.currentLine}")
|
||||
|
||||
if (remainder <= 0) {
|
||||
doc.addNewPage(); pageNum += 1
|
||||
doc.addNewPage(progressIndicator); pageNum += 1
|
||||
}
|
||||
else if (slugHeight > remainder) {
|
||||
val subset = linesOut to remainder
|
||||
@@ -1692,7 +1693,7 @@ object BTeXParser {
|
||||
linesOut += remainder
|
||||
slugHeight -= remainder
|
||||
|
||||
doc.addNewPage(); pageNum += 1
|
||||
doc.addNewPage(progressIndicator); pageNum += 1
|
||||
}
|
||||
|
||||
while (slugHeight > 0) {
|
||||
@@ -1717,8 +1718,8 @@ object BTeXParser {
|
||||
// get width of "word"
|
||||
val searchStrs = slugs.typesettedSlugs.subList(subset.first, subset.first + subset.second)
|
||||
searchStrs.forEach { str ->
|
||||
printdbg("2HREF searchStr: ${str.toReadable()}")
|
||||
printdbg("2HREF object: ${objSeq.toReadable()} (id=${hrefDict[objSeq.toReadable()]})")
|
||||
// printdbg("2HREF searchStr: ${str.toReadable()}")
|
||||
// printdbg("2HREF object: ${objSeq.toReadable()} (id=${hrefDict[objSeq.toReadable()]})")
|
||||
|
||||
val indexOfSequence = str.indexOfSequence(objSeq)
|
||||
|
||||
@@ -1739,8 +1740,8 @@ object BTeXParser {
|
||||
// retrieve the actual word
|
||||
val substr = CodepointSequence(str.subList(wordOffset + 1, wordEnd))
|
||||
|
||||
printdbg("2HREF word: ${substr.toReadable()}")
|
||||
printdbg("2HREF hrefObj: ${hrefObj}")
|
||||
// printdbg("2HREF word: ${substr.toReadable()}")
|
||||
// printdbg("2HREF hrefObj: ${hrefObj}")
|
||||
|
||||
val hrefX = if (objectIsSplit) 0 else hrefObj.x
|
||||
var hrefY = hrefObj.y; if (objectIsSplit) hrefY += doc.lineHeightInPx
|
||||
@@ -1754,7 +1755,7 @@ object BTeXParser {
|
||||
}
|
||||
// target word is on the next line (probably)
|
||||
else {
|
||||
printdbg("2HREF object was cut off by the linebreak")
|
||||
// printdbg("2HREF object was cut off by the linebreak")
|
||||
objectIsSplit = true
|
||||
}
|
||||
}
|
||||
@@ -1768,7 +1769,7 @@ object BTeXParser {
|
||||
slugHeight -= remainder
|
||||
|
||||
if (remainder == height) {
|
||||
doc.addNewPage(); pageNum += 1
|
||||
doc.addNewPage(progressIndicator); pageNum += 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1947,7 +1948,7 @@ object BTeXParser {
|
||||
if (doc.linesPrintedOnPage[doc.currentPage] < doc.pageLines)
|
||||
doc.linesPrintedOnPage[doc.currentPage] += 1
|
||||
else
|
||||
doc.addNewPage()
|
||||
doc.addNewPage(progressIndicator)
|
||||
}
|
||||
|
||||
private data class _HrefObject(val x: Int, val y: Int, val hrefTarget: String)
|
||||
|
||||
@@ -23,6 +23,7 @@ import net.torvald.terrarum.inUse
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.unicode.EMDASH
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
@@ -56,6 +57,9 @@ class BTeXTest : ApplicationAdapter() {
|
||||
it.set(null)
|
||||
}
|
||||
|
||||
private val typesetProgress = AtomicInteger(0)
|
||||
private val renderProgress = AtomicInteger(0)
|
||||
|
||||
override fun create() {
|
||||
Lang
|
||||
TinyAlphNum
|
||||
@@ -76,7 +80,7 @@ class BTeXTest : ApplicationAdapter() {
|
||||
Thread {
|
||||
try {
|
||||
measureTimeMillis {
|
||||
val f = BTeXParser.invoke(Gdx.files.internal("./assets/mods/basegame/books/$filePath"), varMap)
|
||||
val f = BTeXParser.invoke(Gdx.files.internal("./assets/mods/basegame/books/$filePath"), varMap, typesetProgress)
|
||||
document = f.first
|
||||
documentHandler = f.second
|
||||
}.also {
|
||||
@@ -84,7 +88,7 @@ class BTeXTest : ApplicationAdapter() {
|
||||
}
|
||||
|
||||
measureTimeMillis {
|
||||
document.finalise(true)
|
||||
document.finalise(renderProgress, true)
|
||||
}.also {
|
||||
println("Time spent on finalising [ms]: $it")
|
||||
}
|
||||
@@ -151,6 +155,16 @@ class BTeXTest : ApplicationAdapter() {
|
||||
else {
|
||||
batch.color = Color.WHITE
|
||||
Toolkit.drawTextCentered(batch, TinyAlphNum, stage, 1280, 0, 354)
|
||||
|
||||
if (stage.lowercase().startsWith("typesetting")) {
|
||||
val pgCnt = typesetProgress.get()
|
||||
Toolkit.drawTextCentered(batch, TinyAlphNum, "Pages: $pgCnt", 1280, 0, 375)
|
||||
}
|
||||
else if (stage.lowercase().startsWith("rendering")) {
|
||||
val pgCnt = document.pages.size
|
||||
val renderCnt = renderProgress.get()
|
||||
Toolkit.drawTextCentered(batch, TinyAlphNum, "Pages: $renderCnt/$pgCnt", 1280, 0, 375)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user