From 23aac0c1c1d4f718d55cff737dbd1f72cf260546 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 24 Jan 2022 17:34:11 +0900 Subject: [PATCH] I think I've nailed down the RAsup rendering --- assets/devanagari_variable.tga | 2 +- .../torvald/terrarumsansbitmap/GlyphProps.kt | 1 + .../gdx/TerrarumSansBitmap.kt | 52 +++++++++++++++--- testing.PNG | Bin 20934 -> 24688 bytes testtext.txt | 9 ++- work_files/devanagari_variable.psd | 4 +- 6 files changed, 54 insertions(+), 14 deletions(-) diff --git a/assets/devanagari_variable.tga b/assets/devanagari_variable.tga index 40e8729..ec84188 100644 --- a/assets/devanagari_variable.tga +++ b/assets/devanagari_variable.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:32c52fdafc5860e4ea876d0b2ed58da94398de94fd5271f9fe9509f9661cdf0f +oid sha256:e39e686cfdc068d08a3a245d110bf09920f4fd6c4c6a6e1b83c01c09621ca34b size 491538 diff --git a/src/net/torvald/terrarumsansbitmap/GlyphProps.kt b/src/net/torvald/terrarumsansbitmap/GlyphProps.kt index 11a0b24..cc91246 100755 --- a/src/net/torvald/terrarumsansbitmap/GlyphProps.kt +++ b/src/net/torvald/terrarumsansbitmap/GlyphProps.kt @@ -45,6 +45,7 @@ data class GlyphProps( const val STACK_DOWN = 1 const val STACK_BEFORE_N_AFTER = 2 const val STACK_UP_N_DOWN = 3 + const val STACK_DONT = 4 const val DIA_OVERLAY = 2 // const val DIA_JOINER = 2 diff --git a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt index 46c12aa..d8200bf 100755 --- a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt +++ b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt @@ -713,7 +713,12 @@ class TerrarumSansBitmap( else writeOnTop = writeOnTop.ushr(28) and 15 } - val stackWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) } + val stackWhere0 = pixmap.getPixel(codeStartX, codeStartY + 18).tagify() + val stackWhere1 = pixmap.getPixel(codeStartX, codeStartY + 19).tagify() + + val stackWhere = if (stackWhere0 == 0x00FF00FF && stackWhere1 == 0x00FF00FF) + GlyphProps.STACK_DONT + else (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) } glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, IntArray(15), hasKernData, isKernYtype, kerningMask, directiveOpcode, directiveArg1, directiveArg2) @@ -745,7 +750,7 @@ class TerrarumSansBitmap( // if (diacriticsAnchors.any { it.xUsed || it.yUsed }) dbgprn("${code.charInfo()} ${diacriticsAnchors.filter { it.xUsed || it.yUsed }.joinToString()}") // if (directiveOpcode != 0) dbgprn("Directive opcode ${directiveOpcode.toString(2)}: ${code.charInfo()}") // if (glyphProps[code]?.isPragma("replacewith") == true) dbgprn("Replacer: ${code.charInfo()} into ${glyphProps[code]!!.extInfo.map { it.toString(16) }.joinToString()}") - +// if (stackWhere == GlyphProps.STACK_DONT) dbgprn("Diacritics Don't stack: ${code.charInfo()}") } } @@ -1037,6 +1042,16 @@ class TerrarumSansBitmap( val seq2 = CodepointSequence() val yankedCharacters = Stack>() // Stack of ; codepoint use -1 if not applicable + var yankedDevanagariRaStatus = intArrayOf(0,0) // 0: none, 1: consonants, 2: virama, 3: vowel for this syllable + + fun changeRaStatus(n: Int) { + yankedDevanagariRaStatus[0] = yankedDevanagariRaStatus[1] + yankedDevanagariRaStatus[1] = n + } + fun resetRaStatus() { + yankedDevanagariRaStatus[0] = 0 + yankedDevanagariRaStatus[1] = 0 + } fun emptyOutYanked() { while (!yankedCharacters.empty()) { @@ -1170,7 +1185,7 @@ class TerrarumSansBitmap( // 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)) + seq.addAll(ligateIndicConsonants(c, cNext2)) i += 2 } // Unicode Devanagari Rendering Rule R5 @@ -1179,18 +1194,38 @@ class TerrarumSansBitmap( 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 + // in Regex: RA (vir C)+ V* ᴿ [not V && not vir] + else if (yankedDevanagariRaStatus[1] == 1 && c == DEVANAGARI_VIRAMA) { + if (yankedDevanagariRaStatus[0] != 0) + seq.add(c) + changeRaStatus(2) + } + else if (yankedDevanagariRaStatus[1] == 2 && devanagariConsonants.contains(c)) { + seq.add(c) + changeRaStatus(1) + } + else if ((yankedDevanagariRaStatus[1] == 1 || yankedDevanagariRaStatus[1] == 3) && devanagariVerbs.contains(c)) { + seq.add(c) + changeRaStatus(3) + } +// else if (yankedDevanagariRaStatus == 3 && !devanagariVerbs.contains(c)) { + else if (yankedDevanagariRaStatus[1] > 0 && yankedCharacters.peek().second == DEVANAGARI_RA) { // termination or illegal state for Devanagari RA + yankedCharacters.pop() + seq.add(DEVANAGARI_RA_SUPER) + resetRaStatus() + i-- // scan this character again next time + } + else if (c == DEVANAGARI_RA && cNext == DEVANAGARI_VIRAMA && devanagariConsonants.contains(c)) { + yankedCharacters.push(i to c) + changeRaStatus(1) } - // Unicode Devanagari Rendering Rule R2-R4 else if (!isDevanagari(c) && !yankedCharacters.empty()) { emptyOutYanked() seq.add(c) + resetRaStatus() } // WIP // END of devanagari string replacer - // rearrange {letter, before-and-after diacritics} as {before-diacritics, letter, after-diacritics} else if (glyphProps[c]?.stackWhere == GlyphProps.STACK_BEFORE_N_AFTER) { val diacriticsProp = glyphProps[c]!! @@ -1710,6 +1745,7 @@ class TerrarumSansBitmap( private val TAMIL_SHRII = 0xF00EE private val devanagariConsonants = ((0x0915..0x0939) + (0x0958..0x095F) + (0x0978..0x097F) + (0xF0105..0xF01FF)).toIntArray() + private val devanagariVerbs = ((0x093A..0x093C) + (0x093E..0x094C) + (0x094E..0x094F)).toIntArray() private val devanagariBaseConsonants = 0x0915..0x0939 private val devanagariBaseConsonantsWithNukta = 0x0958..0x095F diff --git a/testing.PNG b/testing.PNG index 8a95573bf1ba5a1ae558187477ea38f33a44fe75..c8826a7c0581d555e58234e3050c86e05599e278 100755 GIT binary patch literal 24688 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 X$@%utsP0dU`17IQgVY~?z3@K(hB_ls literal 20934 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