diff --git a/assets/mods/basegame/books/btex.xml b/assets/mods/basegame/books/btex.xml index 8c7fc2ca1..1d518691f 100644 --- a/assets/mods/basegame/books/btex.xml +++ b/assets/mods/basegame/books/btex.xml @@ -9,41 +9,61 @@ + + What Is a Book -

This example book is designed to give you the exampe of the Book Language.

+

This example book is designed to give you the example of the Book Language.

What Really Is a Book
-

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.

+

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.

- -

this page is intentionally left blank

-
+

+ this page is intentionally left blank +

+ + + Writing Book Using Pen and Papers -

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.

+

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.

+ + + Writing Book Using Typewriter -

Typewriters can only write single style of font, therefore chapters and sections are not available.

+

Typewriters can only write single style of font, therefore chapters and + sections are not available.

+ + + Writing Book using Computer -

Writing book using a computer requires a use of the Book Typesetting Engine Extended, or

+

Writing book using a computer requires a use of the Book Typesetting Engine Extended, or

Full Control of the Shape
-

With 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.

+

With 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.

-

This style is controlled using the cover attribute on the root tag, with following values: typewriter, printout, hardcover

+

This style is controlled using the cover attribute on the root tag, + with following values: typewriter, printout, hardcover

-

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.

+

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.

+ + diff --git a/lib/TerrarumSansBitmap.jar b/lib/TerrarumSansBitmap.jar index b2afa551b..e410aa5ab 100644 --- a/lib/TerrarumSansBitmap.jar +++ b/lib/TerrarumSansBitmap.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19cd63d57c4985d2e4f956b2516817941a72cfbf866111e1a2076f9a8ef81443 -size 188141 +oid sha256:ef2bb4f64036ccb2b27f47cb0bb8e34691206170c358d4128512f6aa79f61706 +size 188472 diff --git a/src/net/torvald/btex/BTeXDocument.kt b/src/net/torvald/btex/BTeXDocument.kt index c9f2c65c4..06e0cbf7d 100644 --- a/src/net/torvald/btex/BTeXDocument.kt +++ b/src/net/torvald/btex/BTeXDocument.kt @@ -1,10 +1,8 @@ package net.torvald.terrarum.btex 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.TextureRegion -import net.torvald.terrarum.App import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarumsansbitmap.MovableType @@ -18,9 +16,9 @@ class BTeXDocument { var papersize = "standard" var pageWidth = 420 - var lineHeight = 24 + var lineHeightInPx = 24 var pageLines = 25 - var pageHeight = pageLines * lineHeight + var pageHeight = pageLines * lineHeightInPx companion object { val DEFAULT_PAGE_BACK = Color(0xe1e1d7ff.toInt()) @@ -29,14 +27,26 @@ class BTeXDocument { private val pages = ArrayList() + val currentPage: Int + get() = pages.size - 1 + var currentLine: Int = 0 + private set fun addNewPage(back: Color = DEFAULT_PAGE_BACK) { 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) { pages.last().appendDrawCall(drawCall) + currentLine += drawCall.lineCount } 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) { - fun draw(batch: SpriteBatch, x: Float, y: Float) { +interface BTeXTextDrawCall { + 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) } } +/*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( - val posX: Int, - val posY: Int, + val posX: Int, // position relative to the page start (excluding page margin) + val posY: Int, // position relative to the page start (excluding page margin) val theme: String, val colour: Color, - val text: MovableTypeDrawCall? = null, + val text: BTeXTextDrawCall? = 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) { val px = (posX + x).toFloat() val py = (posY + y).toFloat() @@ -98,4 +124,9 @@ class BTeXDrawCall( else throw Error("Text and Texture are both non-null") } + internal val lineCount = if (text != null) + text.rowEnd - text.rowStart + else + TODO() + } \ No newline at end of file diff --git a/src/net/torvald/btex/BTeXParser.kt b/src/net/torvald/btex/BTeXParser.kt index 0c815efdb..681431a15 100644 --- a/src/net/torvald/btex/BTeXParser.kt +++ b/src/net/torvald/btex/BTeXParser.kt @@ -4,7 +4,11 @@ import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.Color import net.torvald.terrarum.App 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.terrarumsansbitmap.MovableType +import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap import org.xml.sax.Attributes import org.xml.sax.InputSource import org.xml.sax.helpers.DefaultHandler @@ -20,6 +24,9 @@ import kotlin.reflect.full.findAnnotation */ 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: File): BTeXDocument { @@ -39,7 +46,7 @@ object BTeXParser { internal class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() { private val DEFAULT_FONTCOL = Color(0x222222ff) - private val LINE_HEIGHT = doc.lineHeight + private val LINE_HEIGHT = doc.lineHeightInPx private var cover = "" private var inner = "" @@ -56,7 +63,7 @@ object BTeXParser { private val tagStack = ArrayList() // index zero should be "btex" - + private var currentTheme = "" private var spanColour: String? = null @@ -66,6 +73,8 @@ object BTeXParser { private val elemOpeners: HashMap> = HashMap() private val elemClosers: HashMap> = HashMap() + private val paragraphBuffer = StringBuilder() + init { BTeXHandler::class.declaredFunctions.filter { it.findAnnotation() != null }.forEach { println("Tag opener: ${it.name}") @@ -101,14 +110,21 @@ object BTeXParser { } 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") - tagStack.add(tag) + val tag = qName + 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().also { it.putAll((0 until attributes.length).map { attributes.getQName(it) to attributes.getValue(it) }) } - val theTag = tag.uppercase() elemOpeners["processElem$theTag"].let { 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) { @@ -147,8 +163,9 @@ object BTeXParser { val str = String(ch.sliceArray(start until start + length)).replace('\n', ' ').replace(Regex(" +"), " ")//.trim() - if (str.isNotBlank()) { - printdbg("Characters \t\"$str\"") + if (str.isNotEmpty()) { +// printdbg("Characters \t\"$str\"") + paragraphBuffer.append(str) } } @@ -170,16 +187,212 @@ object BTeXParser { typeY += h } + private lateinit var testFont: TerrarumSansBitmap private fun getFont() = when (cover) { "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( - "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( @@ -239,14 +452,35 @@ object BTeXParser { // 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) { + handler.paragraphBuffer.append("BTeX") + } @OpenTag // reflective access is impossible with 'private' - fun processElemBR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + fun processElemCOVER(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + doc.addNewPage(Color(0x6f4a45ff)) + } + @OpenTag // reflective access is impossible with 'private' + fun processElemTOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + doc.addNewPage() + } + + @OpenTag // reflective access is impossible with 'private' + fun processElemMANUSCRIPT(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + doc.addNewPage() + } + + + + + + + + @OpenTag // reflective access is impossible with 'private' + fun processElemBR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + handler.paragraphBuffer.append("\n") } @OpenTag // reflective access is impossible with 'private' @@ -256,12 +490,63 @@ object BTeXParser { @OpenTag // reflective access is impossible with 'private' fun processElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { - } @CloseTag // reflective access is impossible with 'private' 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' @@ -275,6 +560,7 @@ object BTeXParser { fun closeElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) { spanColour = null } + } diff --git a/src/net/torvald/terrarum/tests/BTeXTest.kt b/src/net/torvald/terrarum/tests/BTeXTest.kt index 0797c6b6a..a96211214 100644 --- a/src/net/torvald/terrarum/tests/BTeXTest.kt +++ b/src/net/torvald/terrarum/tests/BTeXTest.kt @@ -1,18 +1,18 @@ 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 org.xml.sax.Attributes -import org.xml.sax.HandlerBase -import org.xml.sax.helpers.DefaultHandler -import java.io.ByteArrayInputStream -import java.io.InputStream -import javax.xml.parsers.SAXParserFactory +import net.torvald.terrarum.btex.BTeXDocument /** * Created by minjaesong on 2023-10-28. */ -fun main() { +class BTeXTest : ApplicationAdapter() { + val csiR = "\u001B[31m" val csiG = "\u001B[32m" val csi0 = "\u001B[m" @@ -27,54 +27,87 @@ fun main() { - + + + What Is a Book -

This example book is designed to give you the exampe of the Book Language.

+

This example book is designed to give you the example of the Book Language.

What Really Is a Book

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.

+ enumerable pages and insertion of other helpful resources, such as illustrations and hyperlinks.

- -

this page is intentionally left blank

-
+

+ this page is intentionally left blank +

+ + + Writing Book Using Pen and Papers -

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.

+

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.

+ + + Writing Book Using Typewriter -

Typewriters can only write single style of font, therefore chapters and sections are not available.

+

Typewriters can only write single style of font, therefore chapters and + sections are not available.

+ + + Writing Book using Computer

Writing book using a computer requires a use of the Book Typesetting Engine Extended, or

Full Control of the Shape
-

With 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.

+

With 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.

-

This style is controlled using the cover attribute on the root tag, with following - values: typewriter, printout, hardcover

+

This style is controlled using the cover attribute on the root tag, + with following values: typewriter, printout, hardcover

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.

+ while Hardcover is considered bound and two pages are presented to the readers.

- + + """ - 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) } \ No newline at end of file