mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
btex chapter and section styling
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
<section>What Really Is a Book</section>
|
<section>What Really Is a Book</section>
|
||||||
|
|
||||||
<p>A book is a collection of texts printed in a special way that allows them to be read easily, with
|
<p>A book is a collection of texts printed in a special way that allows them to be read easily, with
|
||||||
enumerable pages and insertion of other helpful resources, such as illustrations and hyperlinks.</p>
|
enumerable pages and insertion of other helpful resources, such as illustrations and <a href="btex language">hyperlinks</a>.</p>
|
||||||
|
|
||||||
<newpage />
|
<newpage />
|
||||||
|
|
||||||
@@ -34,33 +34,33 @@
|
|||||||
<chapter>Writing Book Using Pen and Papers</chapter>
|
<chapter>Writing Book Using Pen and Papers</chapter>
|
||||||
|
|
||||||
<p><index id="pen and paper" />If you open a book on a writing table, you will be welcomed with a
|
<p><index id="pen and paper" />If you open a book on a writing table, you will be welcomed with a
|
||||||
toolbar used to put other book elements, such as chapters, sections.</p>
|
toolbar used to put other book elements, such as chapters and sections.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<chapter>Writing Book Using Typewriter</chapter>
|
<chapter>Writing Book Using a Typewriter</chapter>
|
||||||
|
|
||||||
<p><index id="typewriter" />Typewriters can only write single style of font, therefore chapters and
|
<p><index id="typewriter" />Typewriters can only write in a single style of font, chapters and
|
||||||
sections are not available.</p>
|
sections are not available.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<chapter>Writing Book using Computer</chapter>
|
<chapter>Writing Book Using a Computer</chapter>
|
||||||
|
|
||||||
<p>Writing book using a computer requires a use of the Book Typesetting Engine Extended, or <btex /></p>
|
<p>Writing book using a computer requires the use of the Book Typesetting Engine Extended, or <btex />.</p>
|
||||||
|
|
||||||
<section>Full Control of the Shape</section>
|
<section>Full Control of the Shape</section>
|
||||||
|
|
||||||
<p><index id="btex language" />With <btex /> you can fully control how your publishing would look like,
|
<p><index id="btex language" />With <btex /> you can fully control how your publishing would look like,
|
||||||
from a pile of papers that look like they have been typed out using typewriter, a pile of papers but a
|
from a pile of papers that look like they have been typed out using typewriter, a pile of papers but a
|
||||||
fully-featured printouts that have illustrations in it, to a fully-featured hardcover book.</p>
|
fully-featured printouts that have illustrations in it, to a true hardcover book.</p>
|
||||||
|
|
||||||
<p><index id="cover" />This style is controlled using the <code>cover</code> attribute on the root tag,
|
<p><index id="cover" />This style is controlled using the <code>cover</code> attribute on the root tag,
|
||||||
with following values: <code>typewriter</code>, <code>printout</code>, <code>hardcover</code></p>
|
with following values: <code>typewriter</code>, <code>printout</code> and <code>hardcover</code>.</p>
|
||||||
|
|
||||||
<p>Typewriter and Printout are considered not bound and readers will only see one page at a time,
|
<p>Typewriter and Printout are considered not-bound and readers will only see one page at a time,
|
||||||
while Hardcover is considered bound and two pages are presented to the readers.</p>
|
while Hardcover is considered bound and two pages are presented to the readers.</p>
|
||||||
|
|
||||||
</manuscript>
|
</manuscript>
|
||||||
|
|||||||
BIN
lib/TerrarumSansBitmap.jar
LFS
BIN
lib/TerrarumSansBitmap.jar
LFS
Binary file not shown.
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarumsansbitmap.MovableType
|
import net.torvald.terrarumsansbitmap.MovableType
|
||||||
|
import net.torvald.terrarumsansbitmap.gdx.CodepointSequence
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-28.
|
* Created by minjaesong on 2023-10-28.
|
||||||
@@ -15,9 +16,9 @@ class BTeXDocument {
|
|||||||
var inner = "standard"
|
var inner = "standard"
|
||||||
var papersize = "standard"
|
var papersize = "standard"
|
||||||
|
|
||||||
var textWidth = 450
|
var textWidth = 480
|
||||||
var lineHeightInPx = 24
|
var lineHeightInPx = 24
|
||||||
var pageLines = 24
|
var pageLines = 20
|
||||||
var textHeight = pageLines * lineHeightInPx
|
var textHeight = pageLines * lineHeightInPx
|
||||||
|
|
||||||
val pageMarginH = 15
|
val pageMarginH = 15
|
||||||
@@ -38,6 +39,9 @@ class BTeXDocument {
|
|||||||
val currentPage: Int
|
val currentPage: Int
|
||||||
get() = pages.size - 1
|
get() = pages.size - 1
|
||||||
|
|
||||||
|
val currentPageObj: BTeXPage
|
||||||
|
get() = pages[currentPage]
|
||||||
|
|
||||||
val pageIndices: IntRange
|
val pageIndices: IntRange
|
||||||
get() = pages.indices
|
get() = pages.indices
|
||||||
|
|
||||||
@@ -72,7 +76,7 @@ class BTeXPage(
|
|||||||
private val drawCalls = ArrayList<BTeXDrawCall>()
|
private val drawCalls = ArrayList<BTeXDrawCall>()
|
||||||
|
|
||||||
fun appendDrawCall(drawCall: BTeXDrawCall) {
|
fun appendDrawCall(drawCall: BTeXDrawCall) {
|
||||||
drawCalls.add(drawCall)
|
if (drawCall.isNotBlank()) drawCalls.add(drawCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(frameDelta: Float, batch: SpriteBatch, x: Int, y: Int, marginH: Int, marginV: Int) {
|
fun render(frameDelta: Float, batch: SpriteBatch, x: Int, y: Int, marginH: Int, marginV: Int) {
|
||||||
@@ -82,6 +86,9 @@ class BTeXPage(
|
|||||||
it.draw(batch, x + marginH, y + marginV)
|
it.draw(batch, x + marginH, y + marginV)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isEmpty() = drawCalls.isEmpty()
|
||||||
|
fun isNotEmpty() = drawCalls.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BTeXTextDrawCall {
|
interface BTeXTextDrawCall {
|
||||||
@@ -103,8 +110,8 @@ data class MovableTypeDrawCall(val movableType: MovableType, override val rowSta
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
class BTeXDrawCall(
|
class BTeXDrawCall(
|
||||||
val posX: Int, // position relative to the page start (excluding page margin)
|
var posX: Int, // position relative to the page start (excluding page margin)
|
||||||
val posY: Int, // position relative to the page start (excluding page margin)
|
var posY: Int, // position relative to the page start (excluding page margin)
|
||||||
val theme: String,
|
val theme: String,
|
||||||
val colour: Color,
|
val colour: Color,
|
||||||
val text: BTeXTextDrawCall? = null,
|
val text: BTeXTextDrawCall? = null,
|
||||||
@@ -132,11 +139,25 @@ class BTeXDrawCall(
|
|||||||
batch.draw(texture, px, py)
|
batch.draw(texture, px, py)
|
||||||
}
|
}
|
||||||
else throw Error("Text and Texture are both non-null")
|
else throw Error("Text and Texture are both non-null")
|
||||||
|
|
||||||
|
extraDrawFun(batch, px, py)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isNotBlank(): Boolean {
|
||||||
|
if (text == null && texture == null) return false
|
||||||
|
if (text is MovableTypeDrawCall && text.movableType.inputText.isBlank()) return false
|
||||||
|
// if (text is RaggedLeftDrawCall && text.raggedType.inputText.isBlank()) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
internal var extraDrawFun: (SpriteBatch, Float, Float) -> Unit = { _,_,_ ->}
|
||||||
internal val lineCount = if (text != null)
|
internal val lineCount = if (text != null)
|
||||||
text.rowEnd - text.rowStart
|
text.rowEnd - text.rowStart
|
||||||
else
|
else
|
||||||
TODO()
|
TODO()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun CodepointSequence.isBlank() = this.all { whitespaces.contains(it) }
|
||||||
|
private val whitespaces = (listOf(0x00, 0x20, 0x3000, 0xA0, 0xAD) + (0x2000..0x200F) + (0x202A..0x202F) + (0x205F..0x206F) + (0xFFFE0..0xFFFFF)).toHashSet()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,11 +2,13 @@ package net.torvald.btex
|
|||||||
|
|
||||||
import com.badlogic.gdx.files.FileHandle
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.btex.BTeXDocument
|
import net.torvald.terrarum.btex.BTeXDocument
|
||||||
import net.torvald.terrarum.btex.BTeXDrawCall
|
import net.torvald.terrarum.btex.BTeXDrawCall
|
||||||
import net.torvald.terrarum.btex.MovableTypeDrawCall
|
import net.torvald.terrarum.btex.MovableTypeDrawCall
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarumsansbitmap.MovableType
|
import net.torvald.terrarumsansbitmap.MovableType
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
||||||
import org.xml.sax.Attributes
|
import org.xml.sax.Attributes
|
||||||
@@ -75,6 +77,9 @@ object BTeXParser {
|
|||||||
|
|
||||||
private val paragraphBuffer = StringBuilder()
|
private val paragraphBuffer = StringBuilder()
|
||||||
|
|
||||||
|
private var lastTagAtDepth = Array(24) { "" }
|
||||||
|
private var pTagCntAtDepth = IntArray(24)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
BTeXHandler::class.declaredFunctions.filter { it.findAnnotation<OpenTag>() != null }.forEach {
|
BTeXHandler::class.declaredFunctions.filter { it.findAnnotation<OpenTag>() != null }.forEach {
|
||||||
println("Tag opener: ${it.name}")
|
println("Tag opener: ${it.name}")
|
||||||
@@ -119,6 +124,10 @@ object BTeXParser {
|
|||||||
if (tagStack.isNotEmpty() && !textTags.contains(tagStack.last()) && textDecorTags.contains(theTag))
|
if (tagStack.isNotEmpty() && !textTags.contains(tagStack.last()) && textDecorTags.contains(theTag))
|
||||||
throw IllegalStateException("Text decoration tag '$theTag' used outside of a text tag (tag stack is ${tagStack.joinToString()})")
|
throw IllegalStateException("Text decoration tag '$theTag' used outside of a text tag (tag stack is ${tagStack.joinToString()})")
|
||||||
|
|
||||||
|
if (lastTagAtDepth[tagStack.size] != "P") pTagCntAtDepth[tagStack.size] = 0
|
||||||
|
if (theTag == "P") pTagCntAtDepth[tagStack.size] += 1
|
||||||
|
lastTagAtDepth[tagStack.size] = theTag
|
||||||
|
|
||||||
tagStack.add(theTag)
|
tagStack.add(theTag)
|
||||||
|
|
||||||
val attribs = HashMap<String, String>().also {
|
val attribs = HashMap<String, String>().also {
|
||||||
@@ -131,10 +140,10 @@ object BTeXParser {
|
|||||||
System.err.println("Unknown tag: $theTag")
|
System.err.println("Unknown tag: $theTag")
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
it.call(this, this, doc, theTag, uri, attribs)
|
it.call(this, this, doc, theTag, uri, attribs, pTagCntAtDepth[tagStack.size])
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
throw BTeXParsingException(e.stackTraceToString())
|
throw BTeXParsingException("processElem$theTag"+"\n"+e.stackTraceToString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,13 +152,15 @@ object BTeXParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun endElement(uri: String, localName: String, qName: String) {
|
override fun endElement(uri: String, localName: String, qName: String) {
|
||||||
|
lastTagAtDepth[tagStack.size] = "xxx"
|
||||||
|
|
||||||
val popped = tagStack.removeLast()
|
val popped = tagStack.removeLast()
|
||||||
|
|
||||||
val theTag = qName.uppercase()
|
val theTag = qName.uppercase()
|
||||||
|
|
||||||
elemClosers["closeElem$theTag"].let {
|
elemClosers["closeElem$theTag"].let {
|
||||||
try {
|
try {
|
||||||
it?.call(this, this, doc, theTag, uri)
|
it?.call(this, this, doc, theTag, uri, pTagCntAtDepth[tagStack.size])
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
throw BTeXParsingException(e.stackTraceToString())
|
throw BTeXParsingException(e.stackTraceToString())
|
||||||
@@ -396,15 +407,15 @@ object BTeXParser {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val pageWidthMap = hashMapOf(
|
private val pageWidthMap = hashMapOf(
|
||||||
"standard" to 450
|
"standard" to 480
|
||||||
)
|
)
|
||||||
private val pageHeightMap = hashMapOf(
|
private val pageHeightMap = hashMapOf(
|
||||||
"standard" to 24
|
"standard" to 20
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemBTEXDOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemBTEXDOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
if (handler.btexOpened) {
|
if (handler.btexOpened) {
|
||||||
throw BTeXParsingException("BTEXDOC tag has already opened")
|
throw BTeXParsingException("BTEXDOC tag has already opened")
|
||||||
}
|
}
|
||||||
@@ -431,7 +442,7 @@ object BTeXParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemPAIR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemPAIR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
if (tagStack.size == 3 && tagStack.getOrNull(1) == "blocklut") {
|
if (tagStack.size == 3 && tagStack.getOrNull(1) == "blocklut") {
|
||||||
blockLut[attribs["key"]!!] = attribs["value"]!!
|
blockLut[attribs["key"]!!] = attribs["value"]!!
|
||||||
}
|
}
|
||||||
@@ -441,35 +452,35 @@ object BTeXParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
attribs["span"]?.let {
|
attribs["span"]?.let {
|
||||||
spanColour = it
|
spanColour = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemTABLEOFCONTENTS(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemTABLEOFCONTENTS(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
// TODO add post-parsing hook to the handler
|
// TODO add post-parsing hook to the handler
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemBTEX(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemBTEX(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
handler.paragraphBuffer.append("BTeX")
|
handler.paragraphBuffer.append("BTeX")
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemCOVER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemCOVER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
doc.addNewPage(Color(0x6f4a45ff))
|
doc.addNewPage(Color(0x6f4a45ff))
|
||||||
handler.spanColour = "white"
|
handler.spanColour = "white"
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemTOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemTOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
doc.addNewPage()
|
doc.addNewPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemMANUSCRIPT(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemMANUSCRIPT(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
doc.addNewPage()
|
doc.addNewPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,48 +491,87 @@ object BTeXParser {
|
|||||||
|
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemBR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemBR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
handler.paragraphBuffer.append("\n")
|
handler.paragraphBuffer.append("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemNEWPAGE(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemNEWPAGE(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
doc.addNewPage()
|
doc.addNewPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
@CloseTag // reflective access is impossible with 'private'
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
fun closeElemFULLPAGEBOX(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
|
fun closeElemFULLPAGEBOX(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) {
|
||||||
doc.addNewPage()
|
doc.addNewPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
fun processElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
fun processElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>, siblingIndex: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@CloseTag
|
@CloseTag
|
||||||
fun closeElemCOVER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
|
fun closeElemCOVER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) {
|
||||||
handler.spanColour = null
|
handler.spanColour = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@CloseTag // reflective access is impossible with 'private'
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
fun closeElemTITLE(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) = closeElemP(handler, doc, theTag, uri)
|
fun closeElemTITLE(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) = closeElemP(handler, doc, theTag, uri, siblingIndex)
|
||||||
@CloseTag // reflective access is impossible with 'private'
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
fun closeElemAUTHOR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) = closeElemP(handler, doc, theTag, uri)
|
fun closeElemAUTHOR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) = closeElemP(handler, doc, theTag, uri, siblingIndex)
|
||||||
@CloseTag // reflective access is impossible with 'private'
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
fun closeElemEDITION(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) = closeElemP(handler, doc, theTag, uri)
|
fun closeElemEDITION(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) = closeElemP(handler, doc, theTag, uri, siblingIndex)
|
||||||
@CloseTag // reflective access is impossible with 'private'
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
fun closeElemCHAPTER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) = closeElemP(handler, doc, theTag, uri)
|
fun closeElemCHAPTER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) {
|
||||||
|
val indent = 16
|
||||||
|
val thePar = "\n" + handler.paragraphBuffer.toString().trim()
|
||||||
|
typesetParagraphs(thePar, handler, doc.textWidth - indent).also {
|
||||||
|
// add indents and adjust text y pos
|
||||||
|
it.forEach {
|
||||||
|
it.posX += indent
|
||||||
|
it.posY -= doc.lineHeightInPx / 2
|
||||||
|
}
|
||||||
|
// add ornamental column on the left
|
||||||
|
it.forEach {
|
||||||
|
it.extraDrawFun = { batch, x, y ->
|
||||||
|
Toolkit.fillArea(batch, x - (indent - 2), y + doc.lineHeightInPx, 6f, (it.lineCount - 1).coerceAtLeast(1) * doc.lineHeightInPx.toFloat())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.paragraphBuffer.clear()
|
||||||
|
}
|
||||||
@CloseTag // reflective access is impossible with 'private'
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
fun closeElemSECTION(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) = closeElemP(handler, doc, theTag, uri)
|
fun closeElemSECTION(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) {
|
||||||
|
val indent = 8
|
||||||
|
val thePar = "\n" + handler.paragraphBuffer.toString().trim()
|
||||||
|
typesetParagraphs(thePar, handler, doc.textWidth - indent).also {
|
||||||
|
// add indents and adjust text y pos
|
||||||
|
it.forEach {
|
||||||
|
it.posX += indent
|
||||||
|
it.posY -= doc.lineHeightInPx / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.paragraphBuffer.clear()
|
||||||
|
}
|
||||||
|
|
||||||
@CloseTag // reflective access is impossible with 'private'
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
fun closeElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
|
fun closeElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) {
|
||||||
val thePar = handler.paragraphBuffer.toString().trim() + "\n"
|
val thePar = (if (siblingIndex > 1) "\u3000" else "") + handler.paragraphBuffer.toString().trim() // indent the strictly non-first pars
|
||||||
printdbg("Par: '$thePar'")
|
typesetParagraphs(thePar, handler)
|
||||||
|
handler.paragraphBuffer.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
|
fun closeElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, siblingIndex: Int) {
|
||||||
|
spanColour = null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun typesetParagraphs(thePar: String, handler: BTeXHandler, width: Int = doc.textWidth): List<BTeXDrawCall> {
|
||||||
val font = getFont()
|
val font = getFont()
|
||||||
val slugs = MovableType(font, thePar, doc.textWidth)
|
val slugs = MovableType(font, thePar, width)
|
||||||
|
|
||||||
|
val drawCalls = ArrayList<BTeXDrawCall>()
|
||||||
|
|
||||||
var remainder = doc.pageLines - doc.currentLine
|
var remainder = doc.pageLines - doc.currentLine
|
||||||
var slugHeight = slugs.height
|
var slugHeight = slugs.height
|
||||||
@@ -540,7 +590,7 @@ object BTeXParser {
|
|||||||
MovableTypeDrawCall(slugs, subset.first, subset.second)
|
MovableTypeDrawCall(slugs, subset.first, subset.second)
|
||||||
)
|
)
|
||||||
|
|
||||||
doc.appendDrawCall(drawCall)
|
doc.appendDrawCall(drawCall); drawCalls.add(drawCall)
|
||||||
|
|
||||||
linesOut += remainder
|
linesOut += remainder
|
||||||
slugHeight -= remainder
|
slugHeight -= remainder
|
||||||
@@ -561,7 +611,7 @@ object BTeXParser {
|
|||||||
MovableTypeDrawCall(slugs, subset.first, subset.second)
|
MovableTypeDrawCall(slugs, subset.first, subset.second)
|
||||||
)
|
)
|
||||||
|
|
||||||
doc.appendDrawCall(drawCall)
|
doc.appendDrawCall(drawCall); drawCalls.add(drawCall)
|
||||||
|
|
||||||
linesOut += remainder
|
linesOut += remainder
|
||||||
slugHeight -= remainder
|
slugHeight -= remainder
|
||||||
@@ -571,19 +621,10 @@ object BTeXParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.paragraphBuffer.clear()
|
// if typesetting the paragraph leaves the first line of new page empty, move the "row cursor" back up
|
||||||
}
|
if (doc.currentLine == 1 && doc.currentPageObj.isEmpty()) doc.currentLine = 0 // '\n' adds empty draw call to the page, which makes isEmpty() to return false
|
||||||
|
|
||||||
@OpenTag // reflective access is impossible with 'private'
|
return drawCalls
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
|
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
|
||||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
|
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||||
import net.torvald.btex.BTeXParser
|
import net.torvald.btex.BTeXParser
|
||||||
import net.torvald.terrarum.FlippingSpriteBatch
|
import net.torvald.terrarum.FlippingSpriteBatch
|
||||||
@@ -34,9 +37,9 @@ class BTeXTest : ApplicationAdapter() {
|
|||||||
<toc><tableofcontents /></toc>
|
<toc><tableofcontents /></toc>
|
||||||
|
|
||||||
<manuscript>
|
<manuscript>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<chapter>What Is a Book</chapter>
|
<chapter>What Is a Book</chapter>
|
||||||
|
|
||||||
<p>This example book is designed to give you the example of the Book Language.</p>
|
<p>This example book is designed to give you the example of the Book Language.</p>
|
||||||
@@ -44,49 +47,49 @@ class BTeXTest : ApplicationAdapter() {
|
|||||||
<section>What Really Is a Book</section>
|
<section>What Really Is a Book</section>
|
||||||
|
|
||||||
<p>A book is a collection of texts printed in a special way that allows them to be read easily, with
|
<p>A book is a collection of texts printed in a special way that allows them to be read easily, with
|
||||||
enumerable pages and insertion of other helpful resources, such as illustrations and hyperlinks.</p>
|
enumerable pages and insertion of other helpful resources, such as illustrations and <a href="btex language">hyperlinks</a>.</p>
|
||||||
|
|
||||||
<newpage />
|
<newpage />
|
||||||
|
|
||||||
<!--<fullpagebox>
|
<fullpagebox>
|
||||||
<p><span colour="grey">
|
<p><span colour="grey">
|
||||||
this page is intentionally left blank
|
this page is intentionally left blank
|
||||||
</span></p>
|
</span></p>
|
||||||
</fullpagebox>-->
|
</fullpagebox>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<chapter>Writing Book Using Pen and Papers</chapter>
|
<chapter>Writing Book Using Pen and Papers</chapter>
|
||||||
|
|
||||||
<p><index id="pen and paper" />If you open a book on a writing table, you will be welcomed with a
|
<p><index id="pen and paper" />If you open a book on a writing table, you will be welcomed with a
|
||||||
toolbar used to put other book elements, such as chapters, sections.</p>
|
toolbar used to put other book elements, such as chapters and sections.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<chapter>Writing Book Using Typewriter</chapter>
|
|
||||||
|
|
||||||
<p><index id="typewriter" />Typewriters can only write single style of font, therefore chapters and
|
|
||||||
|
|
||||||
|
<chapter>Writing Book Using a Typewriter</chapter>
|
||||||
|
|
||||||
|
<p><index id="typewriter" />Typewriters can only write in a single style of font, chapters and
|
||||||
sections are not available.</p>
|
sections are not available.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<chapter>Writing Book using Computer</chapter>
|
|
||||||
|
|
||||||
<p>Writing book using a computer requires a use of the Book Typesetting Engine Extended, or <btex /></p>
|
|
||||||
|
|
||||||
|
<chapter>Writing Book Using a Computer</chapter>
|
||||||
|
|
||||||
|
<p>Writing book using a computer requires the use of the Book Typesetting Engine Extended, or <btex />.</p>
|
||||||
|
|
||||||
<section>Full Control of the Shape</section>
|
<section>Full Control of the Shape</section>
|
||||||
|
|
||||||
<p><index id="btex language" />With <btex /> you can fully control how your publishing would look like,
|
<p><index id="btex language" />With <btex /> you can fully control how your publishing would look like,
|
||||||
from a pile of papers that look like they have been typed out using typewriter, a pile of papers but a
|
from a pile of papers that look like they have been typed out using typewriter, a pile of papers but a
|
||||||
fully-featured printouts that have illustrations in it, to a fully-featured hardcover book.</p>
|
fully-featured printouts that have illustrations in it, to a true hardcover book.</p>
|
||||||
|
|
||||||
<p><index id="cover" />This style is controlled using the <code>cover</code> attribute on the root tag,
|
<p><index id="cover" />This style is controlled using the <code>cover</code> attribute on the root tag,
|
||||||
with following values: <code>typewriter</code>, <code>printout</code>, <code>hardcover</code></p>
|
with following values: <code>typewriter</code>, <code>printout</code> and <code>hardcover</code>.</p>
|
||||||
|
|
||||||
<p>Typewriter and Printout are considered not bound and readers will only see one page at a time,
|
<p>Typewriter and Printout are considered not-bound and readers will only see one page at a time,
|
||||||
while Hardcover is considered bound and two pages are presented to the readers.</p>
|
while Hardcover is considered bound and two pages are presented to the readers.</p>
|
||||||
|
|
||||||
</manuscript>
|
</manuscript>
|
||||||
@@ -94,12 +97,16 @@ class BTeXTest : ApplicationAdapter() {
|
|||||||
<indexpage><tableofindices /></indexpage>
|
<indexpage><tableofindices /></indexpage>
|
||||||
</btexdoc>
|
</btexdoc>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
private lateinit var document: BTeXDocument
|
private lateinit var document: BTeXDocument
|
||||||
private lateinit var batch: FlippingSpriteBatch
|
private lateinit var batch: FlippingSpriteBatch
|
||||||
private lateinit var camera: OrthographicCamera
|
private lateinit var camera: OrthographicCamera
|
||||||
|
|
||||||
|
private lateinit var bg: TextureRegion
|
||||||
|
|
||||||
override fun create() {
|
override fun create() {
|
||||||
batch = FlippingSpriteBatch(1000)
|
batch = FlippingSpriteBatch(1000)
|
||||||
camera = OrthographicCamera(1280f, 720f)
|
camera = OrthographicCamera(1280f, 720f)
|
||||||
@@ -107,20 +114,29 @@ class BTeXTest : ApplicationAdapter() {
|
|||||||
camera.update()
|
camera.update()
|
||||||
batch.projectionMatrix = camera.combined
|
batch.projectionMatrix = camera.combined
|
||||||
|
|
||||||
|
bg = TextureRegion(Texture(Gdx.files.internal("test_assets/Screenshot-1714034883660.png")))
|
||||||
|
|
||||||
document = BTeXParser.invoke(tex)
|
document = BTeXParser.invoke(tex)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var scroll = 0
|
private var scroll = 0
|
||||||
|
|
||||||
|
val pageGap = 6
|
||||||
|
|
||||||
override fun render() {
|
override fun render() {
|
||||||
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
||||||
|
|
||||||
|
val drawX = (1280 - (pageGap + document.pageWidth*2)) / 2
|
||||||
|
val drawY = 100
|
||||||
|
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
batch.draw(bg, 0f, 0f)
|
||||||
|
|
||||||
if (scroll - 1 in document.pageIndices)
|
if (scroll - 1 in document.pageIndices)
|
||||||
document.render(0f, batch, scroll - 1, 12, 12)
|
document.render(0f, batch, scroll - 1, drawX, drawY)
|
||||||
if (scroll in document.pageIndices)
|
if (scroll in document.pageIndices)
|
||||||
document.render(0f, batch, scroll, 12 + (6 + document.pageWidth), 12)
|
document.render(0f, batch, scroll, drawX + (6 + document.pageWidth), drawY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
test_assets/Screenshot-1714034883660.png
LFS
Normal file
BIN
test_assets/Screenshot-1714034883660.png
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user