devanagari ligation wip

This commit is contained in:
minjaesong
2022-01-18 17:56:15 +09:00
parent 0870856674
commit 9675c40216
5 changed files with 291 additions and 135 deletions

Binary file not shown.

View File

@@ -97,19 +97,19 @@ internal typealias Hash = Long
* Created by minjaesong on 2017-06-15.
*/
class TerrarumSansBitmap(
fontDir: String,
val noShadow: Boolean = false,
val flipY: Boolean = false,
val invertShadow: Boolean = false,
var errorOnUnknownChar: Boolean = false,
val textCacheSize: Int = 256,
val debug: Boolean = false,
val shadowAlpha: Float = 0.5f,
val shadowAlphaPremultiply: Boolean = false
fontDir: String,
val noShadow: Boolean = false,
val flipY: Boolean = false,
val invertShadow: Boolean = false,
var errorOnUnknownChar: Boolean = false,
val textCacheSize: Int = 256,
val debug: Boolean = false,
val shadowAlpha: Float = 0.5f,
val shadowAlphaPremultiply: Boolean = false
) : BitmapFont() {
private fun dbgprn(i: Any) { if (debug) println("[${this.javaClass.simpleName}] $i") }
constructor(fontDir: String, noShadow: Boolean, flipY: Boolean, invertShadow: Boolean) : this(fontDir, noShadow, flipY, invertShadow, false, 256, false)
/* This font is a collection of various subsystems, and thus contains copious amount of quick-and-dirty codes.
@@ -158,9 +158,9 @@ class TerrarumSansBitmap(
val b = codePoint.and(0x000F)
val col = r.shl(28) or r.shl(24) or
g.shl(20) or g.shl(16) or
b.shl(12) or b.shl(8) or
0xFF
g.shl(20) or g.shl(16) or
b.shl(12) or b.shl(8) or
0xFF
colourBuffer[codePoint] = col
@@ -385,8 +385,8 @@ class TerrarumSansBitmap(
val c = textBuffer[index]
val sheetID = getSheetType(c)
val (sheetX, sheetY) =
if (index == 0) getSheetwisePosition(0, c)
else getSheetwisePosition(textBuffer[index - 1], c)
if (index == 0) getSheetwisePosition(0, c)
else getSheetwisePosition(textBuffer[index - 1], c)
val hash = getHash(c) // to be used with Bad Transmission Modifier
if (isColourCode(c)) {
@@ -480,10 +480,10 @@ class TerrarumSansBitmap(
}
batch.draw(tempLinotype,
x.toFloat(),
(y - pixmapOffsetY).toFloat() + (if (flipY) (tempLinotype.height) else 0) * scale,
tempLinotype.width.toFloat() * scale,
(tempLinotype.height.toFloat()) * (if (flipY) -1 else 1) * scale
x.toFloat(),
(y - pixmapOffsetY).toFloat() + (if (flipY) (tempLinotype.height) else 0) * scale,
tempLinotype.width.toFloat() * scale,
(tempLinotype.height.toFloat()) * (if (flipY) -1 else 1) * scale
)
}
@@ -852,9 +852,9 @@ class TerrarumSansBitmap(
val nextHangulJungseong1 = toHangulJungseongIndex(str.getOrNull(charIndex + 2) ?: 0) ?: -1
val nextHangulJungseong2 = toHangulJungseongIndex(str.getOrNull(charIndex + 3) ?: 0) ?: -1
if (isHangulJungseong(thisChar) && thisHangulJungseongIndex in hangulPeaksWithExtraWidth && (
nextHangulJungseong1 !in jungseongWide ||
nextHangulJungseong2 !in jungseongWide
)) {
nextHangulJungseong1 !in jungseongWide ||
nextHangulJungseong2 !in jungseongWide
)) {
//dbgprn("char: ${thisChar.charInfo()}\nproperties: $thisProp")
//dbgprn("${thisChar.charInfo()} ${str.getOrNull(charIndex + 2)?.charInfo()} ${str.getOrNull(charIndex + 3)?.charInfo()}")
extraWidth += 1
@@ -869,11 +869,11 @@ class TerrarumSansBitmap(
posXbuffer[charIndex] = -thisProp.nudgeX +
when (itsProp.alignWhere) {
GlyphProps.ALIGN_RIGHT ->
posXbuffer[nonDiacriticCounter] + W_VAR_INIT + alignmentOffset + interchar + kerning + extraWidth
GlyphProps.ALIGN_CENTRE ->
posXbuffer[nonDiacriticCounter] + HALF_VAR_INIT + itsProp.width + alignmentOffset + interchar + kerning + extraWidth
else ->
posXbuffer[nonDiacriticCounter] + itsProp.width + alignmentOffset + interchar + kerning + extraWidth
posXbuffer[nonDiacriticCounter] + W_VAR_INIT + alignmentOffset + interchar + kerning + extraWidth
GlyphProps.ALIGN_CENTRE ->
posXbuffer[nonDiacriticCounter] + HALF_VAR_INIT + itsProp.width + alignmentOffset + interchar + kerning + extraWidth
else ->
posXbuffer[nonDiacriticCounter] + itsProp.width + alignmentOffset + interchar + kerning + extraWidth
}
nonDiacriticCounter = charIndex
@@ -921,48 +921,48 @@ class TerrarumSansBitmap(
// set Y pos according to diacritics position
// if (thisProp.alignWhere == GlyphProps.ALIGN_CENTRE) {
when (thisProp.stackWhere) {
GlyphProps.STACK_DOWN -> {
posYbuffer[charIndex] = H_DIACRITICS * stackDownwardCounter * flipY.toSign()
stackDownwardCounter++
when (thisProp.stackWhere) {
GlyphProps.STACK_DOWN -> {
posYbuffer[charIndex] = H_DIACRITICS * stackDownwardCounter * flipY.toSign()
stackDownwardCounter++
}
GlyphProps.STACK_UP -> {
posYbuffer[charIndex] = -H_DIACRITICS * stackUpwardCounter * flipY.toSign()
// shift down on lowercase if applicable
if (getSheetType(thisChar) in autoShiftDownOnLowercase &&
lastNonDiacriticChar.isLowHeight()) {
//dbgprn("AAARRRRHHHH for character ${thisChar.toHex()}")
//dbgprn("lastNonDiacriticChar: ${lastNonDiacriticChar.toHex()}")
//dbgprn("cond: ${thisProp.alignXPos == GlyphProps.DIA_OVERLAY}, charIndex: $charIndex")
if (diacriticsType == GlyphProps.DIA_OVERLAY)
posYbuffer[charIndex] += H_OVERLAY_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
else
posYbuffer[charIndex] += H_STACKUP_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
}
GlyphProps.STACK_UP -> {
posYbuffer[charIndex] = -H_DIACRITICS * stackUpwardCounter * flipY.toSign()
// shift down on lowercase if applicable
if (getSheetType(thisChar) in autoShiftDownOnLowercase &&
lastNonDiacriticChar.isLowHeight()) {
//dbgprn("AAARRRRHHHH for character ${thisChar.toHex()}")
//dbgprn("lastNonDiacriticChar: ${lastNonDiacriticChar.toHex()}")
//dbgprn("cond: ${thisProp.alignXPos == GlyphProps.DIA_OVERLAY}, charIndex: $charIndex")
if (diacriticsType == GlyphProps.DIA_OVERLAY)
posYbuffer[charIndex] += H_OVERLAY_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
else
posYbuffer[charIndex] += H_STACKUP_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
}
stackUpwardCounter++
stackUpwardCounter++
// dbgprn("lastNonDiacriticChar: ${lastNonDiacriticChar.charInfo()}; stack counter: $stackUpwardCounter")
}
GlyphProps.STACK_UP_N_DOWN -> {
posYbuffer[charIndex] = H_DIACRITICS * stackDownwardCounter * flipY.toSign()
stackDownwardCounter++
posYbuffer[charIndex] = -H_DIACRITICS * stackUpwardCounter * flipY.toSign()
// shift down on lowercase if applicable
if (getSheetType(thisChar) in autoShiftDownOnLowercase &&
lastNonDiacriticChar.isLowHeight()) {
if (diacriticsType == GlyphProps.DIA_OVERLAY)
posYbuffer[charIndex] += H_OVERLAY_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
else
posYbuffer[charIndex] += H_STACKUP_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
}
stackUpwardCounter++
}
// for BEFORE_N_AFTER, do nothing in here
}
GlyphProps.STACK_UP_N_DOWN -> {
posYbuffer[charIndex] = H_DIACRITICS * stackDownwardCounter * flipY.toSign()
stackDownwardCounter++
posYbuffer[charIndex] = -H_DIACRITICS * stackUpwardCounter * flipY.toSign()
// shift down on lowercase if applicable
if (getSheetType(thisChar) in autoShiftDownOnLowercase &&
lastNonDiacriticChar.isLowHeight()) {
if (diacriticsType == GlyphProps.DIA_OVERLAY)
posYbuffer[charIndex] += H_OVERLAY_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
else
posYbuffer[charIndex] += H_STACKUP_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
}
stackUpwardCounter++
}
// for BEFORE_N_AFTER, do nothing in here
}
// }
}
}
@@ -972,8 +972,8 @@ class TerrarumSansBitmap(
if (str.isNotEmpty()) {
val lastCharProp = glyphProps[str.last()]
val penultCharProp = glyphProps[str[nonDiacriticCounter]] ?:
(if (errorOnUnknownChar) throw throw InternalError("No GlyphProps for char '${str[nonDiacriticCounter]}' " +
"(${str[nonDiacriticCounter].charInfo()})") else nullProp)
(if (errorOnUnknownChar) throw throw InternalError("No GlyphProps for char '${str[nonDiacriticCounter]}' " +
"(${str[nonDiacriticCounter].charInfo()})") else nullProp)
posXbuffer[posXbuffer.lastIndex] = 1 + posXbuffer[posXbuffer.lastIndex - 1] + // adding 1 to house the shadow
if (lastCharProp != null && lastCharProp.writeOnTop >= 0) {
val realDiacriticWidth = if (lastCharProp.alignWhere == GlyphProps.ALIGN_CENTRE) {
@@ -1035,17 +1035,30 @@ class TerrarumSansBitmap(
// basically an Unicode NFD with some additional flavours
private fun CodepointSequence.normalise(): CodepointSequence {
val dis = this.utf16to32()
val seq = CodepointSequence()
val seq2 = CodepointSequence()
val yankedCharacters = Stack<Pair<Int, CodePoint>>() // Stack of <Position, CodePoint>; codepoint use -1 if not applicable
fun emptyOutYanked() {
while (!yankedCharacters.empty()) {
val poppedChar = yankedCharacters.pop()
if (poppedChar.second == DEVANAGARI_RA)
seq.add(DEVANAGARI_RA_SUPER)
else
seq.add(yankedCharacters.pop().second)
}
}
var i = 0
this.utf16to32().let { dis ->
while (i < dis.size) {
val c = dis[i]
val cPrev2 = dis.getOrElse(i-2) { -1 }
val cPrev = dis.getOrElse(i-1) { -1 }
val c = dis[i]
val cNext = dis.getOrElse(i+1) { -1 }
val cNext2 = dis.getOrElse(i+2) { -1 }
// can't use regular sliding window as the 'i' value is changed way too often
// LET THE NORMALISATION BEGIN //
@@ -1137,13 +1150,28 @@ class TerrarumSansBitmap(
// END of tamil subsystem implementation
// BEGIN of devanagari string replacer
else if (c == DEVANAGARI_VIRAMA) {
yankedCharacters.push(i-1 to cPrev)
// Unicode Devanagari Rendering Rule R6-R8
// (this must precede the ligaturing-machine coded on the 2nd pass, otherwise the rules below will cause undesirable effects)
else if (devanagariConsonants.contains(c) && cNext == DEVANAGARI_VIRAMA && cNext2 == DEVANAGARI_RA) {
seq.addAll(toRaAppended(c))
i += 2
}
else if (c == DEVANAGARI_RA) {
// Unicode Devanagari Rendering Rule R5
else if (c == DEVANAGARI_RRA && cNext == DEVANAGARI_VIRAMA || c == DEVANAGARI_RA && cNext == DEVANAGARI_VIRAMA && cNext2 == ZWJ) {
seq.add(DEVANAGARI_EYELASH_RA)
i += 1
}
// Unicode Devanagari Rendering Rule R2-R4
else if (c == DEVANAGARI_RA && cNext == DEVANAGARI_VIRAMA && cNext2 != DEVANAGARI_RA) {
yankedCharacters.push(i to c)
i += 1
}
// WIP
// Unicode Devanagari Rendering Rule R2-R4
else if (!isDevanagari(c) && !yankedCharacters.empty()) {
emptyOutYanked()
seq.add(c)
}
// WIP
// END of devanagari string replacer
// rearrange {letter, before-and-after diacritics} as {before-diacritics, letter, after-diacritics}
@@ -1164,7 +1192,11 @@ class TerrarumSansBitmap(
i++
}
emptyOutYanked()
}
// second scan
// swap position of {letter, diacritics that comes before the letter}
i = 1
while (i <= seq.lastIndex) {
@@ -1175,6 +1207,27 @@ class TerrarumSansBitmap(
seq[i] = t
}
val cPrev2 = seq.getOrElse(i-2) { -1 }
val cPrev = seq.getOrElse(i-1) { -1 }
val c = seq[i]
// BEGIN of Devanagari String Replacer 2 (lookbehind type)
// Devanagari Ligations (Lookbehind)
if (devanagariConsonants.contains(cPrev2) && cPrev == DEVANAGARI_VIRAMA && devanagariConsonants.contains(c)) {
i -= 2
repeat(3) { seq.removeAt(i) }
val ligature = ligateIndicConsonants(cPrev2, c)
ligature.forEachIndexed { index, char ->
seq.add(i + index, char)
}
i += ligature.size
}
// END of Devanagari String Replacer 2
i++
}
@@ -1238,8 +1291,8 @@ class TerrarumSansBitmap(
opCue.forEach {
if (pixmap.getPixel(it.first, it.second) and 0xFF == 0) {
pixmap.drawPixel(it.first, it.second,
// the shadow has the same colour, but alpha halved
pxNow.and(0xFFFFFF00.toInt()).or(0x7F)
// the shadow has the same colour, but alpha halved
pxNow.and(0xFFFFFF00.toInt()).or(0x7F)
)
}
}
@@ -1277,13 +1330,13 @@ class TerrarumSansBitmap(
// for now, no semitransparency (in colourcode && spritesheet)
val jobQueue = if (!invertShadow) arrayOf(
1 to 0,
0 to 1,
1 to 1
1 to 0,
0 to 1,
1 to 1
) else arrayOf(
-1 to 0,
0 to -1,
-1 to -1
-1 to 0,
0 to -1,
-1 to -1
)
jobQueue.forEach {
@@ -1328,10 +1381,10 @@ class TerrarumSansBitmap(
}
private fun Color.toRGBA8888() =
(this.r * 255f).toInt().shl(24) or
(this.g * 255f).toInt().shl(16) or
(this.b * 255f).toInt().shl(8) or
(this.a * 255f).toInt()
(this.r * 255f).toInt().shl(24) or
(this.g * 255f).toInt().shl(16) or
(this.b * 255f).toInt().shl(8) or
(this.a * 255f).toInt()
/**
* RGBA8888 representation
@@ -1343,9 +1396,9 @@ class TerrarumSansBitmap(
val otherBytes = IntArray(4) { other.ushr(it * 8).and(255) }
return (thisBytes[0] times256 otherBytes[0]) or
(thisBytes[1] times256 otherBytes[1]).shl(8) or
(thisBytes[2] times256 otherBytes[2]).shl(16) or
(thisBytes[3] times256 otherBytes[3]).shl(24)
(thisBytes[1] times256 otherBytes[1]).shl(8) or
(thisBytes[2] times256 otherBytes[2]).shl(16) or
(thisBytes[3] times256 otherBytes[3]).shl(24)
}
private infix fun Int.times256(other: Int) = multTable255[this][other]
@@ -1548,7 +1601,7 @@ class TerrarumSansBitmap(
private val autoShiftDownOnLowercase = arrayOf(
SHEET_DIACRITICAL_MARKS_VARW
SHEET_DIACRITICAL_MARKS_VARW
)
private val fileList = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!!
@@ -1630,13 +1683,130 @@ class TerrarumSansBitmap(
'j'.toInt() to 0x237
)
private val tamilLigatingConsonants = listOf('க','ங','ச','ஞ','ட','ண','த','ந','ன','ப','ம','ய','ர','ற','ல','ள','ழ','வ').map { it.toInt() }.toIntArray()
private val ZWJ = 0x200D
private val tamilLigatingConsonants = listOf('க','ங','ச','ஞ','ட','ண','த','ந','ன','ப','ம','ய','ர','ற','ல','ள','ழ','வ').map { it.toInt() }.toIntArray()
private val TAMIL_KSSA = 0xF00ED
private val TAMIL_SHRII = 0xF00EE
private val devanagariConsonants = ((0x0915..0x0939) + (0x0958..0x095F) + (0x0978..0x097F) + (0xF0140..0xF01FF)).toIntArray()
private val devanagariBaseConsonants = 0x0915..0x0939
private val devanagariBaseConsonantsWithNukta = 0x0958..0x095F
private val devanagariBaseConsonantsExtended = 0x0978..0x097F
private val devanagariPresentationFormsConsonants = 0xF0140..0xF01FF
private val DEVANAGARI_VIRAMA = 0x94D
private val DEVANAGARI_RA = 0x930
private val DEVANAGARI_RRA = 0x931
private val DEVANAGARI_RA_SUPER = 0xF0104
private val DEVANAGARI_EYELASH_RA = 0xF012A
private val DEVANAGARI_LIG_K_SS = 0xF0181
private val DEVANAGARI_LIG_J_NY = 0xF0184
private val DEVANAGARI_LIG_T_T = 0xF018B
private val DEVANAGARI_LIG_T_R = 0xF0154
private val DEVANAGARI_LIG_SH_R = 0xF0166
private val DEVANAGARI_HALFLIG_K_SS = 0xF012B
private val DEVANAGARI_HALFLIG_J_NY = 0xF012C
private val DEVANAGARI_HALFLIG_T_T = 0xF012D
private val DEVANAGARI_HALFLIG_T_R = 0xF012E
private val DEVANAGARI_HALFLIG_SH_R = 0xF012F
private val DEVANAGARI_SYLL_RU = 0xF0100
private val DEVANAGARI_SYLL_RUU = 0xF0101
private val DEVANAGARI_HALF_FORMS = 0xF0100 // starting point for Devanagari half forms
private val DEVANAGARI_LIG_X_R = 0xF0140 // starting point for Devanagari ligature CONSONANT+RA
private fun CodePoint.toHalfFormOrNull(): CodePoint? {
if (this in devanagariBaseConsonants) return (this - 0x0910 + DEVANAGARI_HALF_FORMS)
if (this in devanagariBaseConsonantsWithNukta) return (this - 0x0920 + DEVANAGARI_HALF_FORMS)
else if (this == DEVANAGARI_LIG_K_SS) return DEVANAGARI_HALFLIG_K_SS
else if (this == DEVANAGARI_LIG_J_NY) return DEVANAGARI_HALFLIG_J_NY
else if (this == DEVANAGARI_LIG_T_T) return DEVANAGARI_HALFLIG_T_T
else if (this == DEVANAGARI_LIG_T_R) return DEVANAGARI_HALFLIG_T_R
else if (this == DEVANAGARI_LIG_SH_R) return DEVANAGARI_HALFLIG_SH_R
// TODO half forms of X_R-ligatures
else return null
}
// TODO use proper version of Virama for respective scripts
private fun CodePoint.toHalfFormOrVirama(): List<CodePoint> = this.toHalfFormOrNull().let {
if (it == null) listOf(this, DEVANAGARI_VIRAMA) else listOf(it)
}
// TODO use proper version of Virama for respective scripts
private fun toRaAppended(c: CodePoint): List<CodePoint> {
if (c in devanagariBaseConsonants) return listOf(c - 0x0910 + DEVANAGARI_LIG_X_R)
else return listOf(c, DEVANAGARI_VIRAMA, DEVANAGARI_RA)
}
private fun ligateIndicConsonants(c1: CodePoint, c2: CodePoint): List<CodePoint> {
if (c2 == DEVANAGARI_RA) return toRaAppended(c1) // Devanagari @.RA
when (c1) {
0x0915 -> /* Devanagari KA */ when (c2) {
0x0924 -> return listOf(0xF0180) // K.TA
0x0937 -> return listOf(DEVANAGARI_LIG_K_SS) // K.SSA
else -> return c1.toHalfFormOrVirama() + c2
}
0x0919 -> /* Devanagari NGA */ when (c2) {
0x0917 -> return listOf(0xF0182) // NG.G
0x092E -> return listOf(0xF0183) // NG.M
else -> return c1.toHalfFormOrVirama() + c2
}
0x091C -> /* Devanagari JA */ when (c2) {
0x091E -> return listOf(DEVANAGARI_LIG_J_NY) // J.NY
else -> return c1.toHalfFormOrVirama() + c2
}
0x091F -> /* Devanagari TTA */ when (c2) {
0x091F -> return listOf(0xF0185) // TT.TT
0x0920 -> return listOf(0xF0186) // TT.TTH
else -> return c1.toHalfFormOrVirama() + c2
}
0x0920 -> /* Devanagari TTHA */ when (c2) {
0x0920 -> return listOf(0xF0187) // TTH.TTH
else -> return c1.toHalfFormOrVirama() + c2
}
0x0921 -> /* Devanagari DDA */ when (c2) {
0x0921 -> return listOf(0xF0188) // DD.DD
0x0922 -> return listOf(0xF0189) // DD.DDH
else -> return c1.toHalfFormOrVirama() + c2
}
0x0922 -> /* Devanagari DDHA */ when (c2) {
0x0922 -> return listOf(0xF018A) // DDH.DDH
else -> return c1.toHalfFormOrVirama() + c2
}
0x0924 -> /* Devanagari TA */ when (c2) {
0x0924 -> return listOf(DEVANAGARI_LIG_T_T) // T.T
else -> return c1.toHalfFormOrVirama() + c2
}
0x0926 -> /* Devanagari DA */ when (c2) {
0x0926 -> return listOf(0xF018C) // D.D
0x0927 -> return listOf(0xF018D) // D.DH
0x092C -> return listOf(0xF018E) // D.B
0x092D -> return listOf(0xF018F) // D.BH
0x092E -> return listOf(0xF0190) // D.M
0x092F -> return listOf(0xF0191) // D.Y
0x0935 -> return listOf(0xF0192) // D.V
else -> return c1.toHalfFormOrVirama() + c2
}
0x0928 -> /* Devanagari NA */ when (c2) {
0x0928 -> return listOf(0xF0193) // N.N
else -> return c1.toHalfFormOrVirama() + c2
}
0x0939 -> /* Devanagari HA */ when (c2) {
0x0923 -> return listOf(0xF0194) // H.NN
0x0928 -> return listOf(0xF0195) // H.N
0x092E -> return listOf(0xF0196) // H.M
0x092F -> return listOf(0xF0197) // H.Y
0x0932 -> return listOf(0xF0198) // H.L
0x0935 -> return listOf(0xF0199) // H.v
else -> return c1.toHalfFormOrVirama() + c2
}
else -> return c1.toHalfFormOrVirama() + c2 // TODO use proper version of Virama for respective scripts
}
}
private fun Int.toHex() = "U+${this.toString(16).padStart(4, '0').toUpperCase()}"
@@ -1689,13 +1859,13 @@ class TerrarumSansBitmap(
*/
private fun getHanInitialRow(i: Int, p: Int, f: Int): Int {
var ret =
if (p in jungseongI) 3
else if (p in jungseongOUComplex) 7
else if (p in jungseongOEWI) 11
else if (p in jungseongOU) 5
else if (p in jungseongEU) 9
else if (p in jungseongYI) 13
else 1
if (p in jungseongI) 3
else if (p in jungseongOUComplex) 7
else if (p in jungseongOEWI) 11
else if (p in jungseongOU) 5
else if (p in jungseongEU) 9
else if (p in jungseongYI) 13
else 1
if (f != 0) ret += 1
@@ -1717,17 +1887,17 @@ class TerrarumSansBitmap(
private fun isHangulJongseong(c: CodePoint) = c in (0x11A8..0x11FF) || c in (0xD7CB..0xD7FB)
private fun toHangulChoseongIndex(c: CodePoint) =
if (!isHangulChoseong(c)) throw IllegalArgumentException("This Hangul sequence does not begin with Choseong (${c.toHex()})")
else if (c in 0x1100..0x115F) c - 0x1100
else c - 0xA960 + 96
if (!isHangulChoseong(c)) throw IllegalArgumentException("This Hangul sequence does not begin with Choseong (${c.toHex()})")
else if (c in 0x1100..0x115F) c - 0x1100
else c - 0xA960 + 96
private fun toHangulJungseongIndex(c: CodePoint) =
if (!isHangulJungseong(c)) null
else if (c in 0x1160..0x11A7) c - 0x1160
else c - 0xD7B0 + 72
if (!isHangulJungseong(c)) null
else if (c in 0x1160..0x11A7) c - 0x1160
else c - 0xD7B0 + 72
private fun toHangulJongseongIndex(c: CodePoint) =
if (!isHangulJongseong(c)) null
else if (c in 0x11A8..0x11FF) c - 0x11A8 + 1
else c - 0xD7CB + 88 + 1
if (!isHangulJongseong(c)) null
else if (c in 0x11A8..0x11FF) c - 0x11A8 + 1
else c - 0xD7CB + 88 + 1
/**
* X-position in the spritesheet
@@ -1821,9 +1991,9 @@ class TerrarumSansBitmap(
private fun kanaIndexX(c: CodePoint) = c % 16
private fun kanaIndexY(c: CodePoint) =
if (c in 0x31F0..0x31FF) 12
else if (c in 0x1B000..0x1B00F) 13
else (c - 0x3040) / 16
if (c in 0x31F0..0x31FF) 12
else if (c in 0x1B000..0x1B00F) 13
else (c - 0x3040) / 16
private fun cjkPunctIndexX(c: CodePoint) = c % 16
private fun cjkPunctIndexY(c: CodePoint) = (c - 0x3000) / 16
@@ -1902,7 +2072,7 @@ class TerrarumSansBitmap(
private fun tamilIndexX(c: CodePoint) = c % 16
private fun tamilIndexY(c: CodePoint) = (if (c < 0xF0000) (c - 0x0B80) else (c - 0xF0040)) / 16
val charsetOverrideDefault = Character.toChars(CHARSET_OVERRIDE_DEFAULT).toSurrogatedString()
val charsetOverrideBulgarian = Character.toChars(CHARSET_OVERRIDE_BG_BG).toSurrogatedString()
val charsetOverrideSerbian = Character.toChars(CHARSET_OVERRIDE_SR_SR).toSurrogatedString()
@@ -1960,12 +2130,12 @@ class TerrarumSansBitmap(
* J·K
*/
private val kerningRules = arrayListOf(
Kem(ing("_`_@___`__"),ing("`_`___@___")), // ул
Kem(ing("_@_`___`__"),ing("`_________")),
Kem(ing("_@_@___`__"),ing("`___@_@___"),1,1),
Kem(ing("_@_@_`_`__"),ing("`_____@___")),
Kem(ing("___`_`____"),ing("`___@_`___")),
Kem(ing("___`_`____"),ing("`_@___`___")),
Kem(ing("_`_@___`__"),ing("`_`___@___")), // ул
Kem(ing("_@_`___`__"),ing("`_________")),
Kem(ing("_@_@___`__"),ing("`___@_@___"),1,1),
Kem(ing("_@_@_`_`__"),ing("`_____@___")),
Kem(ing("___`_`____"),ing("`___@_`___")),
Kem(ing("___`_`____"),ing("`_@___`___")),
)
init {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,17 +1,3 @@
A ดุ ตี ปู่ พี่ ป่ ม่ ปั มั พีุ ทิ่ท่ท่ิ ปิ่ป่ป่ิ ทิ้ ปิ้ มำด มําด
이는 일본의 요미가나(読み仮名)와 비슷한 용법이다.
Sugarさとう설탕砂糖
বাংলাদেশ
தமிழ் லூ லு
QWனோT
னோ
எழுத்து வடிவங்களுக்கு வார்த்தைகள் மற்றும் வாக்கியங்கள் போலவே தொனி, ஒலி பண்பு, தன்மை உண்டு.
க்ஷ ஶ்ரீ க்ஷௌ
फ़ॊण्ज़ीणू क्की क्कि र्क र्त्सा र्र्ल ऱ्ड क्राप् ठ्री त्र् त्र्मोत्र्यो ज्ञज्ञ्रत्त न्न
ह्णह्नह्मह्यह्लह्वह्र णनमयलव ज़्लतान

Binary file not shown.