btex: fixed the paragraph overflows

This commit is contained in:
minjaesong
2024-04-28 18:23:50 +09:00
parent 54663657bd
commit 45b1a344f2
6 changed files with 120 additions and 34 deletions

View File

@@ -121,7 +121,7 @@
</p><p>그것은 어렵지 않다. 우선 그 돈이 무엇보다도 고맙고 반가웠다. </p><p>그것은 어렵지 않다. 우선 그 돈이 무엇보다도 고맙고 반가웠다.
</p><p>어쨌든 나섰다. 나는 좀 야맹증이다. 그래서 될 수 있는 대로 밝은 거리로 돌아다니기로 했다. </p><p>어쨌든 나섰다. 나는 좀 야맹증이다. 그래서 될 수 있는 대로 밝은 거리로 돌아다니기로 했다.
</p><p>그리고는 경성역 일 이등 대합실 한 곁 티이루움에를 들렀다. 그것은 내게는 큰 발견이었다. 거기는 우선 아무도 아는 사람이 안 온다. 설사 왔다가도 곧 돌아가니까 좋다. 나는 날마다 여기 와서 시간을 보내리라 속으로 생각하여 두었다. 제일 여기 시계가 어느 시계보다도 정확하리라는 것이 좋았다. 섣불리 서투른 시계를 보고 그것을 믿고 시간 전에 집에 돌아갔다가 큰 코를 다쳐서는 안 된다. </p><p>그리고는 경성역 일 이등 대합실 한 곁 티이루움에를 들렀다. 그것은 내게는 큰 발견이었다. 거기는 우선 아무도 아는 사람이 안 온다. 설사 왔다가도 곧 돌아가니까 좋다. 나는 날마다 여기 와서 시간을 보내리라 속으로 생각하여 두었다. 제일 여기 시계가 어느 시계보다도 정확하리라는 것이 좋았다. 섣불리 서투른 시계를 보고 그것을 믿고 시간 전에 집에 돌아갔다가 큰 코를 다쳐서는 안 된다.
</p><p>나는 한 복스에 아무것도 없는 것과 마주 앉아서 잘 끓은 커피를 마셨다. 총총한 가운데 여객들 은 그래도 한 잔 커피가 즐거운가보다. 얼른얼른 마시고 무얼 좀 생각하는 것같이 담벼락도 좀 쳐다보고 하다가 곧 나가 버린다. 서글프다. 그러나 내게는 이 서글픈 분위기가 거리의 티이루움들의 그 거추장스러운 분위기보다는 절실하고 마음에 들었다. 이따금 들리는 날카로운 혹은 우렁찬 기적 소리가 모오짜르트보다도 더 가깝다. </p><p>나는 한 복스에 아무것도 없는 것과 마주 앉아서 잘 끓은 커피를 마셨다. 총총한 가운데 여객들은 그래도 한 잔 커피가 즐거운가보다. 얼른얼른 마시고 무얼 좀 생각하는 것같이 담벼락도 좀 쳐다보고 하다가 곧 나가 버린다. 서글프다. 그러나 내게는 이 서글픈 분위기가 거리의 티이루움들의 그 거추장스러운 분위기보다는 절실하고 마음에 들었다. 이따금 들리는 날카로운 혹은 우렁찬 기적 소리가 모오짜르트보다도 더 가깝다.
</p><p>나는 메뉴에 적힌 몇 가지 안 되는 음식 이름을 치읽고 내리읽고 여러 번 읽었다. 그 것들은 아물아물하는 것이 어딘가 내 어렸을 때 동무들 이름과 비슷한 데가 있었다. </p><p>나는 메뉴에 적힌 몇 가지 안 되는 음식 이름을 치읽고 내리읽고 여러 번 읽었다. 그 것들은 아물아물하는 것이 어딘가 내 어렸을 때 동무들 이름과 비슷한 데가 있었다.
</p><p>거기서 얼마나 내가 오래 앉았는지 정신이 오락가락하는 중에 객이 슬며시 뜸해지면서 이 구석 저 구석 걷어치우기 시작하는 것을 보면 아마 닫는 시간이 된 모양이다. 열 한 시가 좀 지났구나, 여기도 결코 내 안주의 곳은 아니구나, 어디 가서 자정을 넘길까? 두루 걱정을 하면서 나는 밖으로 나섰다. 비가 온다. </p><p>거기서 얼마나 내가 오래 앉았는지 정신이 오락가락하는 중에 객이 슬며시 뜸해지면서 이 구석 저 구석 걷어치우기 시작하는 것을 보면 아마 닫는 시간이 된 모양이다. 열 한 시가 좀 지났구나, 여기도 결코 내 안주의 곳은 아니구나, 어디 가서 자정을 넘길까? 두루 걱정을 하면서 나는 밖으로 나섰다. 비가 온다.
</p><p>빗발이 제법 굵은 것이 우비도 우산도 없는 나를 고생을 시킬 작정이다. 그렇다고 이런 괴이한 풍모를 차리고 이 홀에서 어물어물하는 수도 없고 에이 비를 맞으면 맞았지 하고 그냥 나서 버렸다. </p><p>빗발이 제법 굵은 것이 우비도 우산도 없는 나를 고생을 시킬 작정이다. 그렇다고 이런 괴이한 풍모를 차리고 이 홀에서 어물어물하는 수도 없고 에이 비를 맞으면 맞았지 하고 그냥 나서 버렸다.

View File

@@ -0,0 +1,69 @@
<btexdoc cover="hardcover" inner="standard" papersize="standard">
<cover>
<title>The life and strange surprizing adventures of Robinson Crusoe, of York, mariner: who lived eight and twenty years all alone in an un-inhabited island on the coast of America, near the mouth of the great river of Oroonoque; having been cast on shore by shipwreck, wherein all the men perished but himself, with an account how he was at last as strangely deliver'd by pyrates</title>
<author>Daniel Defoe</author>
<edition>The Fourth Edition</edition>
</cover>
<tocpage><tableofcontents /></tocpage>
<manuscript>
<chapter>What Is a Book</chapter>
<p>This example book is designed to give you the example of the Book Language.</p>
<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 <a href="btex language">hyperlinks</a>.</p>
<newpage />
<!--<fullpagebox>
<p><span colour="grey">
this page is intentionally left blank
</span></p>
</fullpagebox>-->
<chapter>Writing a 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
toolbar used to put other book elements, such as chapters and sections.</p>
<chapter>Writing a 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>
<chapter>Writing a 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>
<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 printouts
that have pictures 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,
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,
while Hardcover is considered bound and two pages are presented to the readers.</p>
</manuscript>
<indexpage><tableofindices /></indexpage>
</btexdoc>

Binary file not shown.

View File

@@ -21,14 +21,15 @@ class BTeXDocument {
var textWidth = 480 var textWidth = 480
var lineHeightInPx = 24 var lineHeightInPx = 24
var pageLines = 25 var pageLines = 25
var textHeight = pageLines * lineHeightInPx val textHeight: Int
get() = pageLines * lineHeightInPx
val pageMarginH = 15 val pageMarginH = 15
val pageMarginV = 12 val pageMarginV = 12
val pageWidth: Int val pageDimensionWidth: Int
get() = 2 * pageMarginH + textWidth get() = 2 * pageMarginH + textWidth
val pageHeight: Int val pageDimensionHeight: Int
get() = 2 * pageMarginV + textHeight get() = 2 * pageMarginV + textHeight
companion object { companion object {
@@ -50,12 +51,12 @@ class BTeXDocument {
internal val linesPrintedOnPage = ArrayList<Int>() internal val linesPrintedOnPage = ArrayList<Int>()
fun addNewPage(back: Color = DEFAULT_PAGE_BACK) { fun addNewPage(back: Color = DEFAULT_PAGE_BACK) {
pages.add(BTeXPage(back, pageWidth, pageHeight)) pages.add(BTeXPage(back, pageDimensionWidth, pageDimensionHeight))
linesPrintedOnPage.add(0) linesPrintedOnPage.add(0)
} }
fun addNewPageAt(index: Int, back: Color = DEFAULT_PAGE_BACK) { fun addNewPageAt(index: Int, back: Color = DEFAULT_PAGE_BACK) {
pages.add(index, BTeXPage(back, pageWidth, pageHeight)) pages.add(index, BTeXPage(back, pageDimensionWidth, pageDimensionHeight))
linesPrintedOnPage.add(index, 0) linesPrintedOnPage.add(index, 0)
} }
@@ -109,13 +110,13 @@ class BTeXPage(
interface BTeXTextDrawCall { interface BTeXTextDrawCall {
val rowStart: Int val rowStart: Int
val rowEnd: Int val rows: Int
fun draw(batch: SpriteBatch, x: Float, y: Float) fun draw(doc: BTeXDocument, batch: SpriteBatch, x: Float, y: Float)
} }
data class MovableTypeDrawCall(val movableType: MovableType, override val rowStart: Int, override val rowEnd: Int): BTeXTextDrawCall { data class MovableTypeDrawCall(val movableType: MovableType, override val rowStart: Int, override val rows: Int): BTeXTextDrawCall {
override fun draw(batch: SpriteBatch, x: Float, y: Float) { override fun draw(doc: BTeXDocument, batch: SpriteBatch, x: Float, y: Float) {
movableType.draw(batch, x, y, rowStart, rowEnd) movableType.draw(batch, x, y, rowStart, minOf(rows, doc.pageLines))
} }
} }
@@ -126,6 +127,7 @@ data class MovableTypeDrawCall(val movableType: MovableType, override val rowSta
}*/ }*/
class BTeXDrawCall( class BTeXDrawCall(
val doc: BTeXDocument,
var posX: Int, // position relative to the page start (excluding page margin) var posX: Int, // position relative to the page start (excluding page margin)
var 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,
@@ -150,7 +152,7 @@ class BTeXDrawCall(
batch.color = colour batch.color = colour
if (text != null && texture == null) { if (text != null && texture == null) {
text.draw(batch, px, py) text.draw(doc, batch, px, py)
} }
else if (text == null && texture != null) { else if (text == null && texture != null) {
batch.draw(texture, px, py) batch.draw(texture, px, py)
@@ -178,7 +180,7 @@ class BTeXDrawCall(
internal var extraDrawFun: (SpriteBatch, Float, Float) -> Unit = { _, _, _ ->} internal var extraDrawFun: (SpriteBatch, Float, Float) -> Unit = { _, _, _ ->}
internal val lineCount = if (text != null) internal val lineCount = if (text != null)
text.rowEnd - text.rowStart text.rows
else else
TODO() TODO()

View File

@@ -67,9 +67,9 @@ object BTeXParser {
private var btexOpened = false private var btexOpened = false
private var pageWidth = doc.textWidth // private var pageWidth = doc.textWidth
private var pageLines = doc.pageLines // private var pageLines = doc.pageLines
private var pageHeight = doc.textHeight // private var pageHeight = doc.textHeight
private val blockLut = HashMap<String, ItemID>() private val blockLut = HashMap<String, ItemID>()
@@ -489,17 +489,12 @@ object BTeXParser {
handler.papersize = attribs["papersize"] ?: "standard" handler.papersize = attribs["papersize"] ?: "standard"
//change the "default values" of the document //change the "default values" of the document
handler.pageWidth = pageWidthMap[papersize]!!
handler.pageLines = pageHeightMap[papersize]!!
handler.pageHeight = pageLines * LINE_HEIGHT
doc.textWidth = pageWidth doc.textWidth = pageWidthMap[papersize]!!
doc.textHeight = pageHeight doc.pageLines = pageHeightMap[papersize]!!
} }
handler.btexOpened = true handler.btexOpened = true
printdbg("BTeX document: def=${handler.def}, cover=${handler.cover}, inner=${handler.inner}, papersize=${handler.papersize}, dim=${handler.pageWidth}x${handler.pageHeight} (${handler.pageLines} lines)")
} }
@OpenTag // reflective access is impossible with 'private' @OpenTag // reflective access is impossible with 'private'
@@ -516,6 +511,10 @@ object BTeXParser {
fun processElemTITLE(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) { fun processElemTITLE(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) {
handler.paragraphBuffer.clear() handler.paragraphBuffer.clear()
} }
@OpenTag // reflective access is impossible with 'private'
fun processElemSUBTITLE(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) {
handler.paragraphBuffer.clear()
}
@OpenTag // reflective access is impossible with 'private' @OpenTag // reflective access is impossible with 'private'
fun processElemAUTHOR(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) { fun processElemAUTHOR(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap<String, String>) {
@@ -738,6 +737,12 @@ object BTeXParser {
handler.paragraphBuffer.clear() handler.paragraphBuffer.clear()
} }
@CloseTag // reflective access is impossible with 'private' @CloseTag // reflective access is impossible with 'private'
fun closeElemSUBTITLE(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) {
val thePar = handler.paragraphBuffer.toString().trim()
typesetBookEdition(thePar, handler)
handler.paragraphBuffer.clear()
}
@CloseTag // reflective access is impossible with 'private'
fun closeElemAUTHOR(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) { fun closeElemAUTHOR(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) {
val thePar = handler.paragraphBuffer.toString().trim() val thePar = handler.paragraphBuffer.toString().trim()
typesetBookAuthor(thePar, handler) typesetBookAuthor(thePar, handler)
@@ -746,7 +751,7 @@ object BTeXParser {
@CloseTag // reflective access is impossible with 'private' @CloseTag // reflective access is impossible with 'private'
fun closeElemEDITION(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) { fun closeElemEDITION(handler: BTeXHandler, doc: BTeXDocument, uri: String, siblingIndex: Int) {
val thePar = handler.paragraphBuffer.toString().trim() val thePar = handler.paragraphBuffer.toString().trim()
typesetBookAuthor(thePar, handler) typesetBookEdition(thePar, handler)
handler.paragraphBuffer.clear() handler.paragraphBuffer.clear()
} }
@@ -834,25 +839,33 @@ object BTeXParser {
val label = "\n" + thePar val label = "\n" + thePar
typesetParagraphs(getTitleFont(), label, handler, (doc.textWidth - 16) / 2).also { typesetParagraphs(getTitleFont(), label, handler, (doc.textWidth - 16) / 2).also {
val addedLines = it.sumOf { it.lineCount } val addedLines = it.sumOf { it.lineCount }
doc.linesPrintedOnPage[doc.currentPage] += addedLines + 2 doc.linesPrintedOnPage[doc.currentPage] += addedLines
it.forEach { it.forEach {
it.posX += 8 it.posX += 8
} }
}
}
private fun typesetBookAuthor(thePar: String, handler: BTeXHandler) {
typesetParagraphs(getSubtitleFont(), "\n\n" + thePar, handler, doc.textWidth - 16).also {
it.last().extraDrawFun = { batch, x, y -> it.last().extraDrawFun = { batch, x, y ->
val px = x val px = x
val py = y + doc.lineHeightInPx * (2 * addedLines) + 8 + 11 val py = y + 23
val pw = doc.textWidth - 16f val pw = doc.textWidth - 16f
batch.color = Color(1f,1f,1f,.5f) batch.color = Color(1f,1f,1f,.5f)
Toolkit.fillArea(batch, px, py, pw+1, 2f) Toolkit.fillArea(batch, px, py, pw+1, 2f)
batch.color = Color.WHITE batch.color = Color.WHITE
Toolkit.fillArea(batch, px, py, pw, 1f) Toolkit.fillArea(batch, px, py, pw, 1f)
} }
it.forEach {
it.posX += 8
}
} }
} }
private fun typesetBookAuthor(thePar: String, handler: BTeXHandler) { private fun typesetBookEdition(thePar: String, handler: BTeXHandler) {
typesetParagraphs(getSubtitleFont(), thePar, handler, doc.textWidth - 16).also { typesetParagraphs(getSubtitleFont(), thePar, handler, doc.textWidth - 16).also {
it.forEach { it.forEach {
it.posX += 8 it.posX += 8
@@ -908,9 +921,10 @@ object BTeXParser {
// printdbg("Page: ${doc.currentPage+1}, Line: ${doc.currentLine}") // printdbg("Page: ${doc.currentPage+1}, Line: ${doc.currentLine}")
if (slugHeight > remainder) { if (slugHeight > remainder) {
val subset = linesOut to linesOut + remainder val subset = linesOut to remainder
val drawCall = BTeXDrawCall( val drawCall = BTeXDrawCall(
doc,
0, 0,
doc.linesPrintedOnPage[pageNum] * doc.lineHeightInPx, doc.linesPrintedOnPage[pageNum] * doc.lineHeightInPx,
handler.currentTheme, handler.currentTheme,
@@ -929,9 +943,10 @@ object BTeXParser {
while (slugHeight > 0) { while (slugHeight > 0) {
remainder = minOf(slugHeight, doc.pageLines) remainder = minOf(slugHeight, doc.pageLines)
val subset = linesOut to linesOut + remainder val subset = linesOut to remainder
val drawCall = BTeXDrawCall( val drawCall = BTeXDrawCall(
doc,
0, 0,
doc.linesPrintedOnPage[pageNum] * doc.lineHeightInPx, doc.linesPrintedOnPage[pageNum] * doc.lineHeightInPx,
handler.currentTheme, handler.currentTheme,

View File

@@ -16,7 +16,6 @@ import net.torvald.terrarum.btex.BTeXDocument
import net.torvald.terrarum.ceilToInt import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.gdxClearAndEnableBlend import net.torvald.terrarum.gdxClearAndEnableBlend
import net.torvald.terrarum.inUse import net.torvald.terrarum.inUse
import java.io.FileReader
/** /**
@@ -26,6 +25,7 @@ class BTeXTest : ApplicationAdapter() {
// val filePath = "btex.xml" // val filePath = "btex.xml"
val filePath = "literature/koKR/yisang_nalgae.xml" val filePath = "literature/koKR/yisang_nalgae.xml"
// val filePath = "test.xml"
private lateinit var document: BTeXDocument private lateinit var document: BTeXDocument
@@ -53,7 +53,7 @@ class BTeXTest : ApplicationAdapter() {
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 drawX = (1280 - (pageGap + document.pageDimensionWidth*2)) / 2
val drawY = 24 val drawY = 24
batch.inUse { batch.inUse {
@@ -63,7 +63,7 @@ class BTeXTest : ApplicationAdapter() {
if (scroll - 1 in document.pageIndices) if (scroll - 1 in document.pageIndices)
document.render(0f, batch, scroll - 1, drawX, drawY) document.render(0f, batch, scroll - 1, drawX, drawY)
if (scroll in document.pageIndices) if (scroll in document.pageIndices)
document.render(0f, batch, scroll, drawX + (6 + document.pageWidth), drawY) document.render(0f, batch, scroll, drawX + (6 + document.pageDimensionWidth), drawY)
} }