two more paragraph alignment: raggedleft and centred

This commit is contained in:
minjaesong
2024-05-09 16:47:42 +09:00
parent e2d6d3724c
commit d31b5e4068

View File

@@ -12,7 +12,7 @@ import kotlin.math.*
import kotlin.properties.Delegates import kotlin.properties.Delegates
enum class TypesettingStrategy { enum class TypesettingStrategy {
JUSTIFIED, RAGGED_RIGHT JUSTIFIED, RAGGED_RIGHT, RAGGED_LEFT, CENTRED
} }
/** /**
@@ -92,9 +92,46 @@ class MovableType(
width = maxOf(width, nextPosX + box.width) width = maxOf(width, nextPosX + box.width)
} }
fun dispatchSlug() { fun dispatchSlug(align: TypesettingStrategy) {
// typesettedSlugs.add(slug) val frozen = slug.freezeIntoCodepointSequence(font)
typesettedSlugs.add(slug.freezeIntoCodepointSequence(font))
// insert empty blocks to the left
if (align == TypesettingStrategy.RAGGED_LEFT) {
// has hangables?
val penult = frozen.penultimateOrNull()
val hang = if (penult == null)
0
else if (hangable.contains(penult))
hangWidth
else if (hangableFW.contains(penult))
hangWidthFW
else
0
val diff = paperWidth - (font.getWidthNormalised(frozen) - hang)
if (diff != 0) {
frozen.addAll(0, diff.glueSizeToGlueChars())
}
}
else if (align == TypesettingStrategy.CENTRED) {
// has hangables?
val penult = frozen.penultimateOrNull()
val hang = if (penult == null)
0
else if (hangable.contains(penult))
hangWidth / 2
else if (hangableFW.contains(penult))
hangWidthFW / 2
else
0
val diff = (paperWidth - (font.getWidthNormalised(frozen)) - hang) / 2
if (diff != 0) {
frozen.addAll(0, diff.glueSizeToGlueChars())
}
}
typesettedSlugs.add(frozen)
slug = ArrayList() slug = ArrayList()
slugWidth = 0 slugWidth = 0
@@ -180,21 +217,25 @@ class MovableType(
if (box.isNotGlue()) { if (box.isNotGlue()) {
// deal with the hangables // deal with the hangables
val slugWidthForOverflowCalc = when (strategy) { val slugWidthForOverflowCalc = when (strategy) {
TypesettingStrategy.JUSTIFIED -> if (box.penultimateCharOrNull == null) TypesettingStrategy.JUSTIFIED -> {
slugWidth val penult = box.penultimateCharOrNull
else if (hangable.contains(box.penultimateCharOrNull))
slugWidth - hangWidth
else if (hangableFW.contains(box.penultimateCharOrNull))
slugWidth - hangWidthFW
else
slugWidth
TypesettingStrategy.RAGGED_RIGHT -> slugWidth if (penult == null)
slugWidth
else if (hangable.contains(penult))
slugWidth - hangWidth
else if (hangableFW.contains(penult))
slugWidth - hangWidthFW
else
slugWidth
}
TypesettingStrategy.RAGGED_RIGHT, TypesettingStrategy.RAGGED_LEFT, TypesettingStrategy.CENTRED -> slugWidth
} }
val truePaperWidth = when (strategy) { val truePaperWidth = when (strategy) {
TypesettingStrategy.JUSTIFIED -> paperWidth TypesettingStrategy.JUSTIFIED -> paperWidth
TypesettingStrategy.RAGGED_RIGHT -> paperWidth + 2 TypesettingStrategy.RAGGED_RIGHT, TypesettingStrategy.RAGGED_LEFT, TypesettingStrategy.CENTRED -> paperWidth + 2
} }
// if adding the box would cause overflow // if adding the box would cause overflow
@@ -324,10 +365,10 @@ class MovableType(
} }
// println(" > Line ${typesettedSlugs.size + 1} Final Slug: [ ${slug.map { it.block.text.toReadable() }.joinToString(" | ")} ]") // println(" > Line ${typesettedSlugs.size + 1} Final Slug: [ ${slug.map { it.block.text.toReadable() }.joinToString(" | ")} ]")
dispatchSlug() dispatchSlug(strategy)
} }
// if adding the box would cause overflow (ragged right) // if adding the box would cause overflow (ragged-something, centred)
else if (strategy == TypesettingStrategy.RAGGED_RIGHT) { else {
// remove trailing glues // remove trailing glues
while (slug.lastOrNull()?.block?.isGlue() == true) { while (slug.lastOrNull()?.block?.isGlue() == true) {
slug.removeLast() slug.removeLast()
@@ -335,10 +376,7 @@ class MovableType(
addHyphenatedTail(box) addHyphenatedTail(box)
dispatchSlug() dispatchSlug(strategy)
}
else {
throw UnsupportedOperationException("Unknown typesetting strategy: ${strategy.name}")
} }
} }
// typeset the boxes normally // typeset the boxes normally
@@ -353,7 +391,7 @@ class MovableType(
if (!ignoreThisLine) { if (!ignoreThisLine) {
// println(" > Line ${typesettedSlugs.size + 1} Final Slug: [ ${slug.map { it.block.text.toReadable() }.joinToString(" | ")} ]") // println(" > Line ${typesettedSlugs.size + 1} Final Slug: [ ${slug.map { it.block.text.toReadable() }.joinToString(" | ")} ]")
dispatchSlug() dispatchSlug(strategy)
} }
} // end of lines.forEach } // end of lines.forEach
@@ -736,6 +774,9 @@ class MovableType(
private fun <E> java.util.ArrayList<E>.penultimate(): E { private fun <E> java.util.ArrayList<E>.penultimate(): E {
return this[this.size - 2] return this[this.size - 2]
} }
private fun <E> java.util.ArrayList<E>.penultimateOrNull(): E? {
return this.getOrNull(this.size - 2)
}
private fun penaliseWidening(score: Int, availableGlues: Double): Double = private fun penaliseWidening(score: Int, availableGlues: Double): Double =
100.0 * (score / availableGlues).pow(3.0) 100.0 * (score / availableGlues).pow(3.0)