diff --git a/src/net/torvald/terrarumsansbitmap/MovableType.kt b/src/net/torvald/terrarumsansbitmap/MovableType.kt index 3baeb8a..86735bb 100644 --- a/src/net/torvald/terrarumsansbitmap/MovableType.kt +++ b/src/net/torvald/terrarumsansbitmap/MovableType.kt @@ -81,7 +81,7 @@ class MovableType( /////////////////////////////////////////////////////////////////////////////////////////////// // the slug is likely end with a glue, must take care of it (but don't modify the slug itself) - fun getBadnessW(box: NoTexGlyphLayout): Triple { + fun getBadnessW(box: NoTexGlyphLayout, availableGlues: Int): Triple { val slug = slug.toMutableList() // remove the trailing glue(s?) in the slug copy @@ -96,12 +96,12 @@ class MovableType( slugWidth -= hangWidthFW val difference = (paperWidth - slugWidth).absoluteValue - val badness = penaliseWidening(difference, paperWidth.toDouble()) + val badness = penaliseWidening(difference, availableGlues.toDouble()) return Triple(badness, difference, null) } - fun getBadnessT(box: NoTexGlyphLayout): Triple { + fun getBadnessT(box: NoTexGlyphLayout, availableGlues: Int): Triple { val slug = slug.toMutableList() // add the box to the slug copy @@ -115,22 +115,25 @@ class MovableType( slugWidth -= hangWidthFW val difference = (paperWidth - slugWidth).absoluteValue - val badness = penaliseTightening(difference, paperWidth.toDouble()) + val badness = penaliseTightening(difference, availableGlues.toDouble()) return Triple(badness, difference, null) } - fun getBadnessH(box: NoTexGlyphLayout, diff: Int): Triple { + fun getBadnessH(box: NoTexGlyphLayout, diff: Int, availableGlues: Int): Triple { // don't hyphenate if: // - the word is too short (5 chars or less) // - the word is pre-hyphenated (ends with hyphen-null) val glyphCount = box.text.count { it in 32..0xfffff } if (glyphCount <= (if (paperWidth < 350) 4 else if (paperWidth < 480) 5 else 6) || box.text.penultimate() == 0x2D) - return Triple(2147483648.0, 2147483647, null) + return Triple(1111111111.0, 2147483647, null) val slug = slug.toMutableList() val (hyphHead, hyphTail) = box.text.hyphenate(font, diff).toList().map { createGlyphLayout(font, it) } + if (hyphTail.text.isEmpty()) + return Triple(2222222222.0, 2147483647, null) + // add the hyphHead to the slug copy val nextPosX = (slug.lastOrNull()?.getEndPos() ?: 0) slug.add(Block(nextPosX, hyphHead)) @@ -142,7 +145,7 @@ class MovableType( slugWidth -= hangWidthFW val difference = (paperWidth - slugWidth) - val badness = penaliseHyphenation(difference.absoluteValue, paperWidth.toDouble()) + val badness = penaliseHyphenation(difference.absoluteValue, availableGlues.toDouble()) return Triple(badness, difference, hyphHead to hyphTail) } @@ -168,24 +171,29 @@ class MovableType( // text overflow occured; set the width to the max value width = paperWidth + val initialGlueCount = slug.getGlueSizeSum(font) + // badness: always positive and weighted // widthDelta: can be positive or negative - val (badnessW, widthDeltaW, _) = getBadnessW(box) // widthDeltaW is always positive - val (badnessT, widthDeltaT, _) = getBadnessT(box) // widthDeltaT is always positive - var (badnessH, widthDeltaH, hyph) = getBadnessH(box, box.width - slugWidthForOverflowCalc) // widthDeltaH can be anything + var (badnessW, widthDeltaW, _) = getBadnessW(box, initialGlueCount) // widthDeltaW is always positive + var (badnessT, widthDeltaT, _) = getBadnessT(box, initialGlueCount) // widthDeltaT is always positive + var (badnessH, widthDeltaH, hyph) = getBadnessH(box, box.width - slugWidthForOverflowCalc, initialGlueCount) // widthDeltaH can be anything - val disableHyphThre = 200.0 * paperWidth.toDouble().pow(0.25) + badnessT -= 0.1 // try to break even + badnessH -= 0.01 // try to break even + val disableHyphThre = 5.0 -// println("\nLine: ${slug.map { it.block.text }.filter { it.isNotGlue() }.joinToString(" ") { it.toReadable() }}") -// println("W diff: $widthDeltaW, badness: $badnessW") -// println("T diff: $widthDeltaT, badness: $badnessT") + println("\nLine: ${slug.map { it.block.text }.filter { it.isNotGlue() }.joinToString(" ") { it.toReadable() }}") + println("W diff: $widthDeltaW, badness: $badnessW") + println("T diff: $widthDeltaT, badness: $badnessT") - if ((badnessW <= disableHyphThre || badnessT <= disableHyphThre) && badnessH > minOf(badnessW, badnessT) / 12.0) { -// println("H diff: $widthDeltaH, badness: $badnessH (disabled)") + + if ((badnessW <= disableHyphThre || badnessT <= disableHyphThre)) { + println("H diff: $widthDeltaH, badness: $badnessH (disabled)") badnessH = 2147483648.0 } else { -// println("H diff: $widthDeltaH, badness: $badnessH") + println("H diff: $widthDeltaH, badness: $badnessH") } val (selectedBadness, selectedWidthDelta, selectedStrat) = listOf( @@ -194,6 +202,14 @@ class MovableType( Triple(badnessH, widthDeltaH, "Hyphenate"), ).minByOrNull { it.first }!! + + if (selectedStrat == "Hyphenate") { + val (hyphHead, hyphTail) = hyph as Pair + println("Selected: $selectedStrat (${hyphHead?.text?.toReadable()}, ${hyphTail?.text?.toReadable()}) (badness $selectedBadness, diff $selectedWidthDelta)") + } + else + println("Selected: $selectedStrat (badness $selectedBadness, diff $selectedWidthDelta)") + // println(" Line ${typesettedSlugs.size + 1} Strat: $selectedStrat (badness $selectedBadness, delta $selectedWidthDelta; full badness WTH = $badnessW, $badnessT, $badnessH; full delta WTH = $widthDeltaW, $widthDeltaT, $widthDeltaH)") // println(" Interim Slug: [ ${slug.map { it.block.text.toReadable() }.joinToString(" | ")} ]") @@ -656,12 +672,15 @@ class MovableType( return this[this.size - 2] } - private fun penaliseWidening(score: Int, paperWidth: Double): Double = - pow(score.toDouble(), 2.0) - private fun penaliseTightening(score: Int, paperWidth: Double): Double = - pow(score.toDouble(), 2.0) - private fun penaliseHyphenation(score: Int, paperWidth: Double): Double = - pow(score.toDouble().absoluteValue, 3.0 * tanh(paperWidth / 650.0)) + private fun penaliseWidening(score: Int, availableGlues: Double): Double = + 100.0 * (score / availableGlues).pow(3.0) +// pow(score.toDouble(), 2.0) + private fun penaliseTightening(score: Int, availableGlues: Double): Double = + 100.0 * (score / availableGlues).pow(3.0) +// pow(score.toDouble(), 2.0) + private fun penaliseHyphenation(score: Int, availableGlues: Double): Double = + 100.0 * (score / availableGlues).pow(3.0) +// pow(score.toDouble().absoluteValue, 3.0 * tanh(paperWidth / 650.0)) private fun isVowel(c: CodePoint) = vowels.contains(c) @@ -722,7 +741,7 @@ class MovableType( val hyphenateCandidates = ArrayList() // stores indices val splitCandidates = ArrayList() // stores indices var i = 3 - while (i < this.size - 3) { + while (i < this.size - 4) { val thisChar = this[i] val prevChar = this[i-1] if (isVowel(prevChar) && !isVowel(thisChar) || !isVowel(prevChar) && isVowel(thisChar)) { @@ -914,16 +933,7 @@ class MovableType( val out = CodepointSequence() val input = this.filter { it.block.text.isNotGlue() } - -// println("Blocks:") -// input.forEach { -// println("x ${it.posX}\te ${it.getEndPos()}\tw ${it.block.width}; ${it.block.text.toReadable()}") -// } - - if (input.isEmpty()) { -// println("FreezeSlugs: ${out.toReadable()}") - return out - } + if (input.isEmpty()) return out // process line indents if (input.first().posX > 0) @@ -939,8 +949,6 @@ class MovableType( out.addAll(it.block.text) } -// println("FreezeSlugs: ${out.toReadable()}\n") - return out } @@ -952,6 +960,25 @@ class MovableType( private fun createGlyphLayout(font: TerrarumSansBitmap, str: CodepointSequence): NoTexGlyphLayout { return NoTexGlyphLayout(str, font.getWidthNormalised(str).div(font.scale)) } + + private fun List.getGlueSizeSum(font: TerrarumSansBitmap): Int { + var out = 0 + + val input = this.filter { it.block.text.isNotGlue() } + if (input.isEmpty()) return 0 + + // process blocks + input.forEachIndexed { index, it -> + val posX = it.posX + 1 - font.interchar * 2 + val prevEndPos = if (index == 0) 0 else input[index-1].getEndPos() + if (index > 0 && posX != prevEndPos) { + out += posX - prevEndPos + } + } + + return out + } + } // end of companion object } diff --git a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt index 99e8fe4..0862f2a 100755 --- a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt +++ b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt @@ -759,6 +759,10 @@ class TerrarumSansBitmap( for (i in 0 until 256) { glyphProps[0xF800 + i] = GlyphProps(0) } + + for (i in 0xFFF70..0xFFF9F) { + glyphProps[i] = GlyphProps(0) + } } fun getWidth(text: String) = getWidthNormalised(text.toCodePoints())