more btex tests

This commit is contained in:
minjaesong
2024-04-25 01:29:32 +09:00
parent 76dd9a98e4
commit f154756439
5 changed files with 433 additions and 63 deletions

View File

@@ -9,41 +9,61 @@
<manuscript> <manuscript>
<chapter>What Is a Book</chapter> <chapter>What Is a Book</chapter>
<p>This example book is designed to give you the exampe of the Book Language.</p> <p>This example book is designed to give you the example of the Book Language.</p>
<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 enumerable pages and insertion of other helpful resources, such as illustrations and hyperlinks.</p> <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>
<newpage /> <newpage />
<fullpagebox> <fullpagebox>
<span colour="grey"> <p><span colour="grey">
<p>this page is intentionally left blank</p> this page is intentionally left blank
</span> </span></p>
</fullpagebox> </fullpagebox>
<chapter>Writing Book Using Pen and Papers</chapter> <chapter>Writing Book Using Pen and Papers</chapter>
<p>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> <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>
<chapter>Writing Book Using Typewriter</chapter> <chapter>Writing Book Using Typewriter</chapter>
<p>Typewriters can only write single style of font, therefore chapters and sections are not available.</p> <p><index id="typewriter" />Typewriters can only write single style of font, therefore chapters and
sections are not available.</p>
<chapter>Writing Book using Computer</chapter> <chapter>Writing Book using 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 a 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>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 fully-featured printouts that have illustrations in it, to a fully-featured hardcover book.</p> <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
fully-featured printouts that have illustrations in it, to a fully-featured hardcover book.</p>
<p>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> <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>
<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> <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>
</manuscript> </manuscript>
<indexpage><tableofindices /></indexpage>
</btexdoc> </btexdoc>

Binary file not shown.

View File

@@ -1,10 +1,8 @@
package net.torvald.terrarum.btex package net.torvald.terrarum.btex
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.SpriteBatch 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.App
import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarumsansbitmap.MovableType import net.torvald.terrarumsansbitmap.MovableType
@@ -18,9 +16,9 @@ class BTeXDocument {
var papersize = "standard" var papersize = "standard"
var pageWidth = 420 var pageWidth = 420
var lineHeight = 24 var lineHeightInPx = 24
var pageLines = 25 var pageLines = 25
var pageHeight = pageLines * lineHeight var pageHeight = pageLines * lineHeightInPx
companion object { companion object {
val DEFAULT_PAGE_BACK = Color(0xe1e1d7ff.toInt()) val DEFAULT_PAGE_BACK = Color(0xe1e1d7ff.toInt())
@@ -29,14 +27,26 @@ class BTeXDocument {
private val pages = ArrayList<BTeXPage>() private val pages = ArrayList<BTeXPage>()
val currentPage: Int
get() = pages.size - 1
var currentLine: Int = 0
private set
fun addNewPage(back: Color = DEFAULT_PAGE_BACK) { fun addNewPage(back: Color = DEFAULT_PAGE_BACK) {
pages.add(BTeXPage(back, pageWidth, pageHeight)) pages.add(BTeXPage(back, pageWidth, pageHeight))
currentLine = 0
} }
/**
* Appends draw call to the list. The draw call must be prepared manually so that they would not overflow.
* Use `addNewPage` to append the overflowing text to the next page.
*
* `currentLine` *will* be updated automatically.
*/
fun appendDrawCall(drawCall: BTeXDrawCall) { fun appendDrawCall(drawCall: BTeXDrawCall) {
pages.last().appendDrawCall(drawCall) pages.last().appendDrawCall(drawCall)
currentLine += drawCall.lineCount
} }
fun render(frameDelta: Float, batch: SpriteBatch, page: Int, x: Int, y: Int) { fun render(frameDelta: Float, batch: SpriteBatch, page: Int, x: Int, y: Int) {
@@ -64,21 +74,37 @@ class BTeXPage(
} }
} }
data class MovableTypeDrawCall(val movableType: MovableType, val rowStart: Int, val rowEnd: Int) { interface BTeXTextDrawCall {
fun draw(batch: SpriteBatch, x: Float, y: Float) { val rowStart: Int
val rowEnd: Int
fun draw(batch: SpriteBatch, x: Float, y: Float)
}
data class MovableTypeDrawCall(val movableType: MovableType, override val rowStart: Int, override val rowEnd: Int): BTeXTextDrawCall {
override fun draw(batch: SpriteBatch, x: Float, y: Float) {
movableType.draw(batch, x, y, rowStart, rowEnd) movableType.draw(batch, x, y, rowStart, rowEnd)
} }
} }
/*data class RaggedLeftDrawCall(val raggedType: RaggedType, override val rowStart: Int, override val rowEnd: Int): BTeXTextDrawCall {
override fun draw(batch: SpriteBatch, x: Float, y: Float) {
raggedType.draw(batch, x, y, rowStart, rowEnd)
}
}*/
class BTeXDrawCall( class BTeXDrawCall(
val posX: Int, val posX: Int, // position relative to the page start (excluding page margin)
val posY: Int, val 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: MovableTypeDrawCall? = null, val text: BTeXTextDrawCall? = null,
val texture: TextureRegion? = null, val texture: TextureRegion? = null,
) { ) {
init {
if (text != null && texture != null) throw IllegalArgumentException("Text and Texture are both non-null")
}
fun draw(batch: SpriteBatch, x: Int, y: Int) { fun draw(batch: SpriteBatch, x: Int, y: Int) {
val px = (posX + x).toFloat() val px = (posX + x).toFloat()
val py = (posY + y).toFloat() val py = (posY + y).toFloat()
@@ -98,4 +124,9 @@ class BTeXDrawCall(
else throw Error("Text and Texture are both non-null") else throw Error("Text and Texture are both non-null")
} }
internal val lineCount = if (text != null)
text.rowEnd - text.rowStart
else
TODO()
} }

View File

@@ -4,7 +4,11 @@ import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
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.MovableTypeDrawCall
import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarumsansbitmap.MovableType
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
import org.xml.sax.Attributes import org.xml.sax.Attributes
import org.xml.sax.InputSource import org.xml.sax.InputSource
import org.xml.sax.helpers.DefaultHandler import org.xml.sax.helpers.DefaultHandler
@@ -20,6 +24,9 @@ import kotlin.reflect.full.findAnnotation
*/ */
object BTeXParser { object BTeXParser {
internal val textTags = hashSetOf("P", "TITLE", "AUTHOR", "EDITION", "CHAPTER", "SECTION")
internal val textDecorTags = hashSetOf("SPAN", "CODE")
operator fun invoke(file: FileHandle) = invoke(file.file()) operator fun invoke(file: FileHandle) = invoke(file.file())
operator fun invoke(file: File): BTeXDocument { operator fun invoke(file: File): BTeXDocument {
@@ -39,7 +46,7 @@ object BTeXParser {
internal class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() { internal class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() {
private val DEFAULT_FONTCOL = Color(0x222222ff) private val DEFAULT_FONTCOL = Color(0x222222ff)
private val LINE_HEIGHT = doc.lineHeight private val LINE_HEIGHT = doc.lineHeightInPx
private var cover = "" private var cover = ""
private var inner = "" private var inner = ""
@@ -56,7 +63,7 @@ object BTeXParser {
private val tagStack = ArrayList<String>() // index zero should be "btex" private val tagStack = ArrayList<String>() // index zero should be "btex"
private var currentTheme = ""
private var spanColour: String? = null private var spanColour: String? = null
@@ -66,6 +73,8 @@ object BTeXParser {
private val elemOpeners: HashMap<String, KFunction<*>> = HashMap() private val elemOpeners: HashMap<String, KFunction<*>> = HashMap()
private val elemClosers: HashMap<String, KFunction<*>> = HashMap() private val elemClosers: HashMap<String, KFunction<*>> = HashMap()
private val paragraphBuffer = StringBuilder()
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}")
@@ -101,14 +110,21 @@ object BTeXParser {
} }
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
val tag = qName; if (tagStack.isEmpty() && tag.lowercase() != "btexdoc") throw BTeXParsingException("Document is not BTeX") val tag = qName
tagStack.add(tag) if (tagStack.isEmpty() && tag.lowercase() != "btexdoc") throw BTeXParsingException("Document is not BTeX")
val theTag = tag.uppercase()
if (tagStack.isNotEmpty() && tagStack.any { textTags.contains(it) } && textTags.contains(theTag))
throw IllegalStateException("Text tag '$theTag' used inside of text tags (tag stack is ${tagStack.joinToString()})")
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()})")
tagStack.add(theTag)
val attribs = HashMap<String, String>().also { val attribs = HashMap<String, String>().also {
it.putAll((0 until attributes.length).map { attributes.getQName(it) to attributes.getValue(it) }) it.putAll((0 until attributes.length).map { attributes.getQName(it) to attributes.getValue(it) })
} }
val theTag = tag.uppercase()
elemOpeners["processElem$theTag"].let { elemOpeners["processElem$theTag"].let {
if (it == null) if (it == null)
@@ -123,7 +139,7 @@ object BTeXParser {
} }
} }
// printdbg("Start element \t($tag)") // printdbg("Start element \t($theTag)")
} }
override fun endElement(uri: String, localName: String, qName: String) { override fun endElement(uri: String, localName: String, qName: String) {
@@ -147,8 +163,9 @@ object BTeXParser {
val str = val str =
String(ch.sliceArray(start until start + length)).replace('\n', ' ').replace(Regex(" +"), " ")//.trim() String(ch.sliceArray(start until start + length)).replace('\n', ' ').replace(Regex(" +"), " ")//.trim()
if (str.isNotBlank()) { if (str.isNotEmpty()) {
printdbg("Characters \t\"$str\"") // printdbg("Characters \t\"$str\"")
paragraphBuffer.append(str)
} }
} }
@@ -170,16 +187,212 @@ object BTeXParser {
typeY += h typeY += h
} }
private lateinit var testFont: TerrarumSansBitmap
private fun getFont() = when (cover) { private fun getFont() = when (cover) {
"typewriter" -> TODO() "typewriter" -> TODO()
else -> App.fontGame else -> App.fontGame ?: let {
if (!::testFont.isInitialized) testFont = TerrarumSansBitmap(App.FONT_DIR)
testFont
}
} }
private fun getSpanColour(): Color = spanColourMap.getOrDefault(spanColour, DEFAULT_FONTCOL) private val hexColRegexRGBshort = Regex("#[0-9a-fA-F]{3,3}")
private val hexColRegexRGB = Regex("#[0-9a-fA-F]{6,6}")
private fun getSpanColour(): Color = if (spanColour == null) DEFAULT_FONTCOL
else if (spanColour!!.matches(hexColRegexRGB)) {
val rs = spanColour!!.substring(1,3)
val gs = spanColour!!.substring(3,5)
val bs = spanColour!!.substring(5,7)
val r = rs.toInt(16) / 255f
val g = gs.toInt(16) / 255f
val b = bs.toInt(16) / 255f
Color(r, g, b, 1f)
}
else if (spanColour!!.matches(hexColRegexRGBshort)) {
val rs = spanColour!!.substring(1,2)
val gs = spanColour!!.substring(2,3)
val bs = spanColour!!.substring(3,4)
val r = rs.toInt(16) / 15f
val g = gs.toInt(16) / 15f
val b = bs.toInt(16) / 15f
Color(r, g, b, 1f)
}
else
spanColourMap.getOrDefault(spanColour, DEFAULT_FONTCOL)
// list of CSS named colours (list supports up to CSS Colors Level 4)
private val spanColourMap = hashMapOf( private val spanColourMap = hashMapOf(
"grey" to Color.LIGHT_GRAY "black" to Color(0x000000ff.toInt()),
"silver" to Color(0xc0c0c0ff.toInt()),
"gray" to Color(0x808080ff.toInt()),
"white" to Color(0xffffffff.toInt()),
"maroon" to Color(0x800000ff.toInt()),
"red" to Color(0xff0000ff.toInt()),
"purple" to Color(0x800080ff.toInt()),
"fuchsia" to Color(0xff00ffff.toInt()),
"green" to Color(0x008000ff.toInt()),
"lime" to Color(0x00ff00ff.toInt()),
"olive" to Color(0x808000ff.toInt()),
"yellow" to Color(0xffff00ff.toInt()),
"navy" to Color(0x000080ff.toInt()),
"blue" to Color(0x0000ffff.toInt()),
"teal" to Color(0x008080ff.toInt()),
"aqua" to Color(0x00ffffff.toInt()),
"aliceblue" to Color(0xf0f8ffff.toInt()),
"antiquewhite" to Color(0xfaebd7ff.toInt()),
"aqua" to Color(0x00ffffff.toInt()),
"aquamarine" to Color(0x7fffd4ff.toInt()),
"azure" to Color(0xf0ffffff.toInt()),
"beige" to Color(0xf5f5dcff.toInt()),
"bisque" to Color(0xffe4c4ff.toInt()),
"black" to Color(0x000000ff.toInt()),
"blanchedalmond" to Color(0xffebcdff.toInt()),
"blue" to Color(0x0000ffff.toInt()),
"blueviolet" to Color(0x8a2be2ff.toInt()),
"brown" to Color(0xa52a2aff.toInt()),
"burlywood" to Color(0xdeb887ff.toInt()),
"cadetblue" to Color(0x5f9ea0ff.toInt()),
"chartreuse" to Color(0x7fff00ff.toInt()),
"chocolate" to Color(0xd2691eff.toInt()),
"coral" to Color(0xff7f50ff.toInt()),
"cornflowerblue" to Color(0x6495edff.toInt()),
"cornsilk" to Color(0xfff8dcff.toInt()),
"crimson" to Color(0xdc143cff.toInt()),
"cyan" to Color(0x00ffffff.toInt()),
"darkblue" to Color(0x00008bff.toInt()),
"darkcyan" to Color(0x008b8bff.toInt()),
"darkgoldenrod" to Color(0xb8860bff.toInt()),
"darkgray" to Color(0xa9a9a9ff.toInt()),
"darkgreen" to Color(0x006400ff.toInt()),
"darkgrey" to Color(0xa9a9a9ff.toInt()),
"darkkhaki" to Color(0xbdb76bff.toInt()),
"darkmagenta" to Color(0x8b008bff.toInt()),
"darkolivegreen" to Color(0x556b2fff.toInt()),
"darkorange" to Color(0xff8c00ff.toInt()),
"darkorchid" to Color(0x9932ccff.toInt()),
"darkred" to Color(0x8b0000ff.toInt()),
"darksalmon" to Color(0xe9967aff.toInt()),
"darkseagreen" to Color(0x8fbc8fff.toInt()),
"darkslateblue" to Color(0x483d8bff.toInt()),
"darkslategray" to Color(0x2f4f4fff.toInt()),
"darkslategrey" to Color(0x2f4f4fff.toInt()),
"darkturquoise" to Color(0x00ced1ff.toInt()),
"darkviolet" to Color(0x9400d3ff.toInt()),
"deeppink" to Color(0xff1493ff.toInt()),
"deepskyblue" to Color(0x00bfffff.toInt()),
"dimgray" to Color(0x696969ff.toInt()),
"dimgrey" to Color(0x696969ff.toInt()),
"dodgerblue" to Color(0x1e90ffff.toInt()),
"firebrick" to Color(0xb22222ff.toInt()),
"floralwhite" to Color(0xfffaf0ff.toInt()),
"forestgreen" to Color(0x228b22ff.toInt()),
"fuchsia" to Color(0xff00ffff.toInt()),
"gainsboro" to Color(0xdcdcdcff.toInt()),
"ghostwhite" to Color(0xf8f8ffff.toInt()),
"gold" to Color(0xffd700ff.toInt()),
"goldenrod" to Color(0xdaa520ff.toInt()),
"gray" to Color(0x808080ff.toInt()),
"green" to Color(0x008000ff.toInt()),
"greenyellow" to Color(0xadff2fff.toInt()),
"grey" to Color(0x808080ff.toInt()),
"honeydew" to Color(0xf0fff0ff.toInt()),
"hotpink" to Color(0xff69b4ff.toInt()),
"indianred" to Color(0xcd5c5cff.toInt()),
"indigo" to Color(0x4b0082ff.toInt()),
"ivory" to Color(0xfffff0ff.toInt()),
"khaki" to Color(0xf0e68cff.toInt()),
"lavender" to Color(0xe6e6faff.toInt()),
"lavenderblush" to Color(0xfff0f5ff.toInt()),
"lawngreen" to Color(0x7cfc00ff.toInt()),
"lemonchiffon" to Color(0xfffacdff.toInt()),
"lightblue" to Color(0xadd8e6ff.toInt()),
"lightcoral" to Color(0xf08080ff.toInt()),
"lightcyan" to Color(0xe0ffffff.toInt()),
"lightgoldenrodyellow" to Color(0xfafad2ff.toInt()),
"lightgray" to Color(0xd3d3d3ff.toInt()),
"lightgreen" to Color(0x90ee90ff.toInt()),
"lightgrey" to Color(0xd3d3d3ff.toInt()),
"lightpink" to Color(0xffb6c1ff.toInt()),
"lightsalmon" to Color(0xffa07aff.toInt()),
"lightseagreen" to Color(0x20b2aaff.toInt()),
"lightskyblue" to Color(0x87cefaff.toInt()),
"lightslategray" to Color(0x778899ff.toInt()),
"lightslategrey" to Color(0x778899ff.toInt()),
"lightsteelblue" to Color(0xb0c4deff.toInt()),
"lightyellow" to Color(0xffffe0ff.toInt()),
"lime" to Color(0x00ff00ff.toInt()),
"limegreen" to Color(0x32cd32ff.toInt()),
"linen" to Color(0xfaf0e6ff.toInt()),
"magenta" to Color(0xff00ffff.toInt()),
"maroon" to Color(0x800000ff.toInt()),
"mediumaquamarine" to Color(0x66cdaaff.toInt()),
"mediumblue" to Color(0x0000cdff.toInt()),
"mediumorchid" to Color(0xba55d3ff.toInt()),
"mediumpurple" to Color(0x9370dbff.toInt()),
"mediumseagreen" to Color(0x3cb371ff.toInt()),
"mediumslateblue" to Color(0x7b68eeff.toInt()),
"mediumspringgreen" to Color(0x00fa9aff.toInt()),
"mediumturquoise" to Color(0x48d1ccff.toInt()),
"mediumvioletred" to Color(0xc71585ff.toInt()),
"midnightblue" to Color(0x191970ff.toInt()),
"mintcream" to Color(0xf5fffaff.toInt()),
"mistyrose" to Color(0xffe4e1ff.toInt()),
"moccasin" to Color(0xffe4b5ff.toInt()),
"navajowhite" to Color(0xffdeadff.toInt()),
"navy" to Color(0x000080ff.toInt()),
"oldlace" to Color(0xfdf5e6ff.toInt()),
"olive" to Color(0x808000ff.toInt()),
"olivedrab" to Color(0x6b8e23ff.toInt()),
"orange" to Color(0xffa500ff.toInt()),
"orangered" to Color(0xff4500ff.toInt()),
"orchid" to Color(0xda70d6ff.toInt()),
"palegoldenrod" to Color(0xeee8aaff.toInt()),
"palegreen" to Color(0x98fb98ff.toInt()),
"paleturquoise" to Color(0xafeeeeff.toInt()),
"palevioletred" to Color(0xdb7093ff.toInt()),
"papayawhip" to Color(0xffefd5ff.toInt()),
"peachpuff" to Color(0xffdab9ff.toInt()),
"peru" to Color(0xcd853fff.toInt()),
"pink" to Color(0xffc0cbff.toInt()),
"plum" to Color(0xdda0ddff.toInt()),
"powderblue" to Color(0xb0e0e6ff.toInt()),
"purple" to Color(0x800080ff.toInt()),
"rebeccapurple" to Color(0x663399ff.toInt()),
"red" to Color(0xff0000ff.toInt()),
"rosybrown" to Color(0xbc8f8fff.toInt()),
"royalblue" to Color(0x4169e1ff.toInt()),
"saddlebrown" to Color(0x8b4513ff.toInt()),
"salmon" to Color(0xfa8072ff.toInt()),
"sandybrown" to Color(0xf4a460ff.toInt()),
"seagreen" to Color(0x2e8b57ff.toInt()),
"seashell" to Color(0xfff5eeff.toInt()),
"sienna" to Color(0xa0522dff.toInt()),
"silver" to Color(0xc0c0c0ff.toInt()),
"skyblue" to Color(0x87ceebff.toInt()),
"slateblue" to Color(0x6a5acdff.toInt()),
"slategray" to Color(0x708090ff.toInt()),
"slategrey" to Color(0x708090ff.toInt()),
"snow" to Color(0xfffafaff.toInt()),
"springgreen" to Color(0x00ff7fff.toInt()),
"steelblue" to Color(0x4682b4ff.toInt()),
"tan" to Color(0xd2b48cff.toInt()),
"teal" to Color(0x008080ff.toInt()),
"thistle" to Color(0xd8bfd8ff.toInt()),
"tomato" to Color(0xff6347ff.toInt()),
"transparent" to Color(0),
"turquoise" to Color(0x40e0d0ff.toInt()),
"violet" to Color(0xee82eeff.toInt()),
"wheat" to Color(0xf5deb3ff.toInt()),
"white" to Color(0xffffffff.toInt()),
"whitesmoke" to Color(0xf5f5f5ff.toInt()),
"yellow" to Color(0xffff00ff.toInt()),
"yellowgreen" to Color(0x9acd32ff.toInt())
) )
private val pageWidthMap = hashMapOf( private val pageWidthMap = hashMapOf(
@@ -239,14 +452,35 @@ object BTeXParser {
// TODO add post-parsing hook to the handler // TODO add post-parsing hook to the handler
} }
@OpenTag // reflective access is impossible with 'private'
fun processElemBTEX(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
handler.paragraphBuffer.append("BTeX")
}
@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 processElemCOVER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
doc.addNewPage(Color(0x6f4a45ff))
}
@OpenTag // reflective access is impossible with 'private'
fun processElemTOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
doc.addNewPage()
}
@OpenTag // reflective access is impossible with 'private'
fun processElemMANUSCRIPT(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
doc.addNewPage()
}
@OpenTag // reflective access is impossible with 'private'
fun processElemBR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
handler.paragraphBuffer.append("\n")
} }
@OpenTag // reflective access is impossible with 'private' @OpenTag // reflective access is impossible with 'private'
@@ -256,12 +490,63 @@ object BTeXParser {
@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>) {
} }
@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) {
printdbg("Par: ${handler.paragraphBuffer}")
val font = getFont()
val slugs = MovableType(font, handler.paragraphBuffer.toString(), doc.pageWidth)
var remainder = doc.pageLines - doc.currentLine
var slugHeight = slugs.height
var linesOut = 0
if (slugHeight > remainder) {
val subset = linesOut to linesOut + remainder
val drawCall = BTeXDrawCall(
0,
remainder * doc.pageLines,
handler.currentTheme,
handler.getSpanColour(),
MovableTypeDrawCall(slugs, subset.first, subset.second)
)
doc.appendDrawCall(drawCall)
linesOut += remainder
slugHeight -= remainder
doc.addNewPage()
}
while (slugHeight > 0) {
remainder = minOf(slugHeight, doc.pageLines)
val subset = linesOut to linesOut + remainder
val drawCall = BTeXDrawCall(
0,
0,
handler.currentTheme,
handler.getSpanColour(),
MovableTypeDrawCall(slugs, subset.first, subset.second)
)
doc.appendDrawCall(drawCall)
linesOut += remainder
slugHeight -= remainder
if (remainder == doc.pageLines) {
doc.addNewPage()
}
}
handler.paragraphBuffer.clear()
} }
@OpenTag // reflective access is impossible with 'private' @OpenTag // reflective access is impossible with 'private'
@@ -275,6 +560,7 @@ object BTeXParser {
fun closeElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) { fun closeElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
spanColour = null spanColour = null
} }
} }

View File

@@ -1,18 +1,18 @@
package net.torvald.terrarum.tests package net.torvald.terrarum.tests
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.glutils.ShaderProgram
import net.torvald.btex.BTeXParser import net.torvald.btex.BTeXParser
import org.xml.sax.Attributes import net.torvald.terrarum.btex.BTeXDocument
import org.xml.sax.HandlerBase
import org.xml.sax.helpers.DefaultHandler
import java.io.ByteArrayInputStream
import java.io.InputStream
import javax.xml.parsers.SAXParserFactory
/** /**
* Created by minjaesong on 2023-10-28. * Created by minjaesong on 2023-10-28.
*/ */
fun main() { class BTeXTest : ApplicationAdapter() {
val csiR = "\u001B[31m" val csiR = "\u001B[31m"
val csiG = "\u001B[32m" val csiG = "\u001B[32m"
val csi0 = "\u001B[m" val csi0 = "\u001B[m"
@@ -28,31 +28,43 @@ fun main() {
<manuscript> <manuscript>
<chapter>What Is a Book</chapter> <chapter>What Is a Book</chapter>
<p>This example book is designed to give you the exampe of the Book Language.</p> <p>This example book is designed to give you the example of the Book Language.</p>
<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 hyperlinks.</p>
<newpage /> <newpage />
<fullpagebox> <fullpagebox>
<span colour="grey"> <p><span colour="grey">
<p>this page is intentionally left blank</p> this page is intentionally left blank
</span> </span></p>
</fullpagebox> </fullpagebox>
<chapter>Writing Book Using Pen and Papers</chapter> <chapter>Writing Book Using Pen and Papers</chapter>
<p>If you open a book on a writing table, you will be welcomed with a toolbar used to put other book <p><index id="pen and paper" />If you open a book on a writing table, you will be welcomed with a
elements, such as chapters, sections.</p> toolbar used to put other book elements, such as chapters, sections.</p>
<chapter>Writing Book Using Typewriter</chapter> <chapter>Writing Book Using Typewriter</chapter>
<p>Typewriters can only write single style of font, therefore chapters and sections are not available.</p> <p><index id="typewriter" />Typewriters can only write single style of font, therefore chapters and
sections are not available.</p>
<chapter>Writing Book using Computer</chapter> <chapter>Writing Book using Computer</chapter>
@@ -60,21 +72,42 @@ fun main() {
<section>Full Control of the Shape</section> <section>Full Control of the Shape</section>
<p>With <btex /> you can fully control how your publishing would look like, from a pile of papers that <p><index id="btex language" />With <btex /> you can fully control how your publishing would look like,
look like they have been typed out using typewriter, a pile of papers but a fully-featured printouts that from a pile of papers that look like they have been typed out using typewriter, a pile of papers but a
have illustrations in it, to a fully-featured hardcover book.</p> fully-featured printouts that have illustrations in it, to a fully-featured hardcover book.</p>
<p>This style is controlled using the <code>cover</code> attribute on the root tag, with following <p><index id="cover" />This style is controlled using the <code>cover</code> attribute on the root tag,
values: <code>typewriter</code>, <code>printout</code>, <code>hardcover</code></p> with following values: <code>typewriter</code>, <code>printout</code>, <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>
</btexdoc>
<indexpage><tableofindices /></indexpage>
</btexdoc>
""" """
val doku = BTeXParser(tex) private lateinit var document: BTeXDocument
override fun create() {
document = BTeXParser.invoke(tex)
}
}
fun main() {
ShaderProgram.pedantic = false
val appConfig = Lwjgl3ApplicationConfiguration()
appConfig.useVsync(false)
appConfig.setResizable(false)
appConfig.setWindowedMode(1280, 720)
appConfig.setForegroundFPS(60)
appConfig.setOpenGLEmulation(Lwjgl3ApplicationConfiguration.GLEmulation.GL30, 3, 2)
Lwjgl3Application(BTeXTest(), appConfig)
} }