diff --git a/FontTestGDX/src/FontTestGDX.kt b/FontTestGDX/src/FontTestGDX.kt index 6659dfa..a846e06 100755 --- a/FontTestGDX/src/FontTestGDX.kt +++ b/FontTestGDX/src/FontTestGDX.kt @@ -9,6 +9,7 @@ import com.badlogic.gdx.graphics.glutils.FrameBuffer import com.badlogic.gdx.utils.ScreenUtils import com.badlogic.gdx.utils.StreamUtils import net.torvald.terrarumsansbitmap.MovableType +import net.torvald.terrarumsansbitmap.gdx.CodepointSequence import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap import java.io.File import java.io.IOException @@ -29,7 +30,7 @@ class FontTestGDX : Game() { lateinit var camera: OrthographicCamera - private val testing = true + private val testing = false private val demotextName = if (testing) "testtext.txt" else "demotext_unaligned.txt" private val outimageName = if (testing) "testing.PNG" else "demo.PNG" @@ -45,6 +46,8 @@ class FontTestGDX : Game() { override fun create() { font = TerrarumSansBitmap("./assets", debug = true, flipY = false, errorOnUnknownChar = false, shadowAlpha = 0.5f) // must test for two flipY cases +// font.scale = 2 +// font.interchar = 1 testtex = TextureRegion(Texture("./testtex.tga")) @@ -73,6 +76,19 @@ class FontTestGDX : Game() { Gdx.input.inputProcessor = Navigator(this) + println(font.charsetOverrideCodestyle) + println(font.charsetOverrideDefault) + + val cs1 = CodepointSequence(listOf(0, 65, 0)) + val cs2 = CodepointSequence(listOf(0, 65)) + val cs3 = CodepointSequence(listOf(65, 0)) + val cs4 = CodepointSequence(listOf(65)) + println("w1: ${font.getWidthNormalised(cs1)}; ${font.getWidth(cs1)}") + println("w2: ${font.getWidthNormalised(cs2)}; ${font.getWidth(cs2)}") + println("w3: ${font.getWidthNormalised(cs3)}; ${font.getWidth(cs3)}") + println("w4: ${font.getWidthNormalised(cs4)}; ${font.getWidth(cs4)}") + println("These four numbers must match, even with interchar > 0") + layout = font.typesetParagraph(batch, inputText, TEXW - 48) } @@ -332,7 +348,7 @@ class FlippingSpriteBatch(size: Int = 1000) : SpriteBatch(size) { } lateinit var appConfig: Lwjgl3ApplicationConfiguration -const val TEXW = 480 + 48 +const val TEXW = 800 const val TEXH = 24 * 170 const val WIDTH = TEXW diff --git a/assets/hentaigana_variable.tga b/assets/hentaigana_variable.tga new file mode 100644 index 0000000..adbf3e7 --- /dev/null +++ b/assets/hentaigana_variable.tga @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f4f5e0cef947e30ae509f25fdd91e9ecdebf4af0c5e1c6b38e1f59a5e5c7741 +size 471058 diff --git a/demo.PNG b/demo.PNG index 469895f..ba012a4 100644 Binary files a/demo.PNG and b/demo.PNG differ diff --git a/demotext_unaligned.txt b/demotext_unaligned.txt index 6aa56eb..bb22694 100755 --- a/demotext_unaligned.txt +++ b/demotext_unaligned.txt @@ -100,6 +100,10 @@ How multilingual? Real multilingual! τ޳Œβ€£ Full support for Old Korean/Jeju dialect orthographyτ€€€ +τ»¬π›€†π›„†π›‚¦π›‚Œπ›‚»π›‚Άπ›»π›¦π›ƒΆπ›‚‘π›ƒΊπ›„šπ›„‹π›€™π›ƒ«π›Ÿπ›„€π››π›«π›‚—π›‚π›ƒ­π›ƒ‘π›€‹π›‚œπ›€•π›€¬π›ƒŸπ›ƒ…π›€΄π›‚±π›€Έπ›€π›²π›€„π›€Ώπ›€£π›ƒ₯π›ƒ”π›ƒŽπ›ˆγ‚‘π›‚―π›ƒ™π›•π›π›„τ€€€ + +τ޳Œβ€£ Full support for Archaic Kana/Hentaiganaτ€€€ + τƒ―Supported Unicode Blocks:τ€€€ ⁃ Basic Latin diff --git a/font_drawing_template.png b/font_drawing_template.png index d763760..d5135fb 100755 Binary files a/font_drawing_template.png and b/font_drawing_template.png differ diff --git a/glyph_height_pos_annotation.png b/glyph_height_pos_annotation.png index 1e6585e..0fd8b19 100755 Binary files a/glyph_height_pos_annotation.png and b/glyph_height_pos_annotation.png differ diff --git a/src/net/torvald/terrarumsansbitmap/MovableType.kt b/src/net/torvald/terrarumsansbitmap/MovableType.kt index 1ef9d53..c4dcf09 100644 --- a/src/net/torvald/terrarumsansbitmap/MovableType.kt +++ b/src/net/torvald/terrarumsansbitmap/MovableType.kt @@ -18,11 +18,16 @@ import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.NQSP import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.OBJ import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.PSP import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.QUARTER_EMSP +import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.SHEET_BRAILLE_VARW +import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.SHEET_CUSTOM_SYM +import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.SHEET_HENTAIGANA_VARW +import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.SHEET_TSALAGI_VARW import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.SHY import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.SIX_PER_EMSP import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.THREE_PER_EMSP import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.THSP import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.ZWSP +import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.codeRange import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.getHash import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.glueCharToGlueSize import kotlin.math.* @@ -101,7 +106,10 @@ class MovableType( var ignoreThisLine = false fun dequeue() = boxes.removeFirst() - fun addHyphenatedTail(box: NoTexGlyphLayout) = boxes.add(0, box) + fun addHyphenatedTail(box: NoTexGlyphLayout) { +// println("addHyphenatedTail ${box.text.toReadable()}") + boxes.add(0, box) + } fun addToSlug(box: NoTexGlyphLayout) { val nextPosX = slug.getSlugEndPos() slug.add(Block(nextPosX, box)) @@ -393,6 +401,7 @@ class MovableType( } } + if (slug.isNotEmpty()) moveSlugsToFitTheWidth(operation, slug, selectedWidthDelta.absoluteValue) // put the trailing word back into the upcoming words @@ -418,6 +427,7 @@ class MovableType( // insert hyphHead into the slug addToSlug(hyphHead) + if (slug.isNotEmpty()) moveSlugsToFitTheWidth(operation, slug, selectedWidthDelta.absoluteValue) // put the tail into the upcoming words @@ -454,10 +464,11 @@ class MovableType( // println(" > Line ${typesettedSlugs.size + 1} Final Slug: [ ${slug.map { it.block.text.toReadable() }.joinToString(" | ")} ]") dispatchSlug(strategy, 0) } + } // end of lines.forEach height = typesettedSlugs.size - } } + } } // end of INIT fun draw(batch: SpriteBatch, x: Int, y: Int, lineStart: Int = 0, linesToDraw: Int = 2147483647, lineHeight: Int = TerrarumSansBitmap.LINE_HEIGHT) = draw(batch, x.toFloat(), y.toFloat(), lineStart, linesToDraw, lineHeight) @@ -505,6 +516,8 @@ class MovableType( private fun CodePoint.toHex() = "U+${this.toString(16).padStart(4, '0').toUpperCase()}" private fun moveSlugsToFitTheWidth(operation: Int, slug: ArrayList, selectedWidthDelta: Int) { +// if (slug.isEmpty()) return + var gluesInfo = slug.mapIndexed { index, block -> block to index }.filter { (block, index) -> block.block.isGlue() }.let { @@ -518,6 +531,7 @@ class MovableType( val prevBlockEndsWith = if (index == 0) null else slug[index - 1].block.penultimateCharOrNull // last() will just return {NUL} Triple(block, index, prevBlockEndsWith) }.filter { it.third != null } + // if there are no glues, put spaces between all characters if (gluesInfo.isEmpty()) { gluesInfo = slug.subList(1, slug.size).mapIndexed { index, block -> @@ -819,6 +833,11 @@ class MovableType( sendoutBox() appendToBuffer(c0) } + else if (c0.isSymbol()) { + if (glue > 0) sendoutGlue() + sendoutBox() + appendToBuffer(c0) + } else { if (!isHangulPK(c0) && !c0.isWesternPunctOrQuotes() && !c0.isCJpunct() && !c0.isParens() && isHangulPK(cM ?: 0)) { sendoutBox() @@ -895,6 +914,8 @@ class MovableType( private fun CodePoint?.isMajuscule() = if (this == null) false else Character.isUpperCase(this) private fun CodePoint?.isMiniscule() = if (this == null) false else Character.isLowerCase(this) + private fun CodePoint?.isSymbol() = if (this == null) false else uniSymbolTable.contains(this) + /** * Hyphenates the word at the middle ("paragraph" -> "para-graph") * @@ -1163,6 +1184,212 @@ class MovableType( private fun List.getSlugEndPos(): Int { return this.lastOrNull()?.getEndPos() ?: 0 } + + private val uniSymbolTable = ( 0x0024..0x002b step 7) + + ( 0x003c..0x003e) + + ( 0x005e..0x0060 step 2) + + ( 0x007c..0x007e step 2) + + ( 0x00a2..0x00a6) + + ( 0x00a8..0x00a9) + + ( 0x00ac..0x00ae step 2) + + ( 0x00af..0x00b1) + + ( 0x00b4..0x00b8 step 4) + + ( 0x00d7..0x00f7 step 32) + + ( 0x02c2..0x02c5) + + ( 0x02d2..0x02df) + + ( 0x02e5..0x02eb) + + ( 0x02ed..0x02ef step 2) + + ( 0x02f0..0x02ff) + + ( 0x0375..0x0384 step 15) + + ( 0x0385..0x03f6 step 113) + + ( 0x0482..0x058d step 267) + + ( 0x058e..0x058f) + + ( 0x0606..0x0608) + + ( 0x060b..0x060e step 3) + + ( 0x060f..0x06de step 207) + + ( 0x06e9..0x06fd step 20) + + ( 0x06fe..0x07f6 step 248) + + ( 0x07fe..0x07ff) + + ( 0x0888..0x09f2 step 362) + + ( 0x09f3..0x09fa step 7) + + ( 0x09fb..0x0af1 step 246) + + ( 0x0b70..0x0bf3 step 131) + + ( 0x0bf4..0x0bfa) + + ( 0x0c7f..0x0d4f step 208) + + ( 0x0d79..0x0e3f step 198) + + ( 0x0f01..0x0f03) + + ( 0x0f13..0x0f15 step 2) + + ( 0x0f16..0x0f17) + + ( 0x0f1a..0x0f1f) + + ( 0x0f34..0x0f38 step 2) + + ( 0x0fbe..0x0fc5) + + ( 0x0fc7..0x0fcc) + + ( 0x0fce..0x0fcf) + + ( 0x0fd5..0x0fd8) + + ( 0x109e..0x109f) + + ( 0x1390..0x1399) + + ( 0x166d..0x17db step 366) + + ( 0x1940..0x19de step 158) + + ( 0x19df..0x19ff) + + ( 0x1b61..0x1b6a) + + ( 0x1b74..0x1b7c) + + ( 0x1fbd..0x1fbf step 2) + + ( 0x1fc0..0x1fc1) + + ( 0x1fcd..0x1fcf) + + ( 0x1fdd..0x1fdf) + + ( 0x1fed..0x1fef) + + ( 0x1ffd..0x1ffe) + + ( 0x2044..0x2052 step 14) + + ( 0x207a..0x207c) + + ( 0x208a..0x208c) + + ( 0x20a0..0x20c0) + + ( 0x2100..0x2101) + + ( 0x2103..0x2106) + + ( 0x2108..0x2109) + + ( 0x2114..0x2116 step 2) + + ( 0x2117..0x2118) + + ( 0x211e..0x2123) + + ( 0x2125..0x2129 step 2) + + ( 0x212e..0x213a step 12) + + ( 0x213b..0x2140 step 5) + + ( 0x2141..0x2144) + + ( 0x214a..0x214d) + + ( 0x214f..0x218a step 59) + + ( 0x218b..0x2190 step 5) + + ( 0x2191..0x2307) + + ( 0x230c..0x2328) + + ( 0x232b..0x2426) + + ( 0x2440..0x244a) + + ( 0x249c..0x24e9) + + ( 0x2500..0x2767) + + ( 0x2794..0x27c4) + + ( 0x27c7..0x27e5) + + ( 0x27f0..0x2982) + + ( 0x2999..0x29d7) + + ( 0x29dc..0x29fb) + + ( 0x29fe..0x2b73) + + ( 0x2b76..0x2b95) + + ( 0x2b97..0x2bff) + + ( 0x2ce5..0x2cea) + + ( 0x2e50..0x2e51) + + ( 0x2e80..0x2e99) + + ( 0x2e9b..0x2ef3) + + ( 0x2f00..0x2fd5) + + ( 0x2ff0..0x2ffb) + + ( 0x3004..0x3012 step 14) + + ( 0x3013..0x3020 step 13) + + ( 0x3036..0x3037) + + ( 0x303e..0x303f) + + ( 0x309b..0x309c) + + ( 0x3190..0x3191) + + ( 0x3196..0x319f) + + ( 0x31c0..0x31e3) + + ( 0x3200..0x321e) + + ( 0x322a..0x3247) + + ( 0x3250..0x3260 step 16) + + ( 0x3261..0x327f) + + ( 0x328a..0x32b0) + + ( 0x32c0..0x33ff) + + ( 0x4dc0..0x4dff) + + ( 0xa490..0xa4c6) + + ( 0xa700..0xa716) + + ( 0xa720..0xa721) + + ( 0xa789..0xa78a) + + ( 0xa828..0xa82b) + + ( 0xa836..0xa839) + + ( 0xaa77..0xaa79) + + ( 0xab5b..0xab6a step 15) + + ( 0xab6b..0xfb29 step 20414) + + ( 0xfbb2..0xfbc2) + + ( 0xfd40..0xfd4f) + + ( 0xfdcf..0xfdfc step 45) + + ( 0xfdfd..0xfdff) + + ( 0xfe62..0xfe64 step 2) + + ( 0xfe65..0xfe66) + + ( 0xfe69..0xff04 step 155) + + ( 0xff0b..0xff1c step 17) + + ( 0xff1d..0xff1e) + + ( 0xff3e..0xff40 step 2) + + ( 0xff5c..0xff5e step 2) + + ( 0xffe0..0xffe6) + + ( 0xffe8..0xffee) + + ( 0xfffc..0xfffd) + + (0x10137..0x1013f) + + (0x10179..0x10189) + + (0x1018c..0x1018e) + + (0x10190..0x1019c) + + (0x101a0..0x101d0 step 48) + + (0x101d1..0x101fc) + + (0x10877..0x10878) + + (0x10ac8..0x1173f step 3191) + + (0x11fd5..0x11ff1) + + (0x16b3c..0x16b3f) + + (0x16b45..0x1bc9c step 20823) + + (0x1cf50..0x1cfc3) + + (0x1d000..0x1d0f5) + + (0x1d100..0x1d126) + + (0x1d129..0x1d164) + + (0x1d16a..0x1d16c) + + (0x1d183..0x1d184) + + (0x1d18c..0x1d1a9) + + (0x1d1ae..0x1d1ea) + + (0x1d200..0x1d241) + + (0x1d245..0x1d300 step 187) + + (0x1d301..0x1d356) + + (0x1d6c1..0x1d6db step 26) + + (0x1d6fb..0x1d715 step 26) + + (0x1d735..0x1d74f step 26) + + (0x1d76f..0x1d789 step 26) + + (0x1d7a9..0x1d7c3 step 26) + + (0x1d800..0x1d9ff) + + (0x1da37..0x1da3a) + + (0x1da6d..0x1da74) + + (0x1da76..0x1da83) + + (0x1da85..0x1da86) + + (0x1e14f..0x1e2ff step 432) + + (0x1ecac..0x1ecb0 step 4) + + (0x1ed2e..0x1eef0 step 450) + + (0x1eef1..0x1f000 step 271) + + (0x1f001..0x1f02b) + + (0x1f030..0x1f093) + + (0x1f0a0..0x1f0ae) + + (0x1f0b1..0x1f0bf) + + (0x1f0c1..0x1f0cf) + + (0x1f0d1..0x1f0f5) + + (0x1f10d..0x1f1ad) + + (0x1f1e6..0x1f202) + + (0x1f210..0x1f23b) + + (0x1f240..0x1f248) + + (0x1f250..0x1f251) + + (0x1f260..0x1f265) + + (0x1f300..0x1f6d7) + + (0x1f6dc..0x1f6ec) + + (0x1f6f0..0x1f6fc) + + (0x1f700..0x1f776) + + (0x1f77b..0x1f7d9) + + (0x1f7e0..0x1f7eb) + + (0x1f7f0..0x1f800 step 16) + + (0x1f801..0x1f80b) + + (0x1f810..0x1f847) + + (0x1f850..0x1f859) + + (0x1f860..0x1f887) + + (0x1f890..0x1f8ad) + + (0x1f8b0..0x1f8b1) + + (0x1f900..0x1fa53) + + (0x1fa60..0x1fa6d) + + (0x1fa70..0x1fa7c) + + (0x1fa80..0x1fa88) + + (0x1fa90..0x1fabd) + + (0x1fabf..0x1fac5) + + (0x1face..0x1fadb) + + (0x1fae0..0x1fae8) + + (0x1faf0..0x1faf8) + + (0x1fb00..0x1fb92) + + (0x1fb94..0x1fbca) + + codeRange[SHEET_BRAILLE_VARW] + + codeRange[SHEET_CUSTOM_SYM] + + codeRange[SHEET_TSALAGI_VARW] + + codeRange[SHEET_HENTAIGANA_VARW] } // end of companion object } diff --git a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt index 72fd4b0..3e96019 100755 --- a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt +++ b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt @@ -891,6 +891,7 @@ class TerrarumSansBitmap( SHEET_DEVANAGARI2_INTERNAL_VARW -> devanagari2IndexY(ch) SHEET_CODESTYLE_ASCII_VARW -> codestyleAsciiIndexY(ch) SHEET_ALPHABETIC_PRESENTATION_FORMS -> alphabeticPresentationFormsY(ch) + SHEET_HENTAIGANA_VARW -> hentaiganaIndexY(ch) else -> ch / 16 } @@ -2557,6 +2558,7 @@ class TerrarumSansBitmap( internal const val SHEET_DEVANAGARI2_INTERNAL_VARW = 36 internal const val SHEET_CODESTYLE_ASCII_VARW = 37 internal const val SHEET_ALPHABETIC_PRESENTATION_FORMS = 38 + internal const val SHEET_HENTAIGANA_VARW = 39 internal const val SHEET_UNKNOWN = 254 @@ -2622,13 +2624,14 @@ class TerrarumSansBitmap( "devanagari_internal_extrawide_variable.tga", "pua_codestyle_ascii_variable.tga", "alphabetic_presentation_forms_extrawide_variable.tga", + "hentaigana_variable.tga", ) internal val codeRange = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!! 0..0xFF, // SHEET_ASCII_VARW (0x1100..0x11FF) + (0xA960..0xA97F) + (0xD7B0..0xD7FF), // SHEET_HANGUL, because Hangul Syllables are disassembled prior to the render 0x100..0x17F, // SHEET_EXTA_VARW 0x180..0x24F, // SHEET_EXTB_VARW - (0x3040..0x30FF) + (0x31F0..0x31FF) + (0x1B000..0x1B001), // SHEET_KANA + (0x3040..0x30FF) + (0x31F0..0x31FF), // SHEET_KANA 0x3000..0x303F, // SHEET_CJK_PUNCT 0x3400..0x9FFF, // SHEET_UNIHAN 0x400..0x52F, // SHEET_CYRILIC_VARW @@ -2663,6 +2666,7 @@ class TerrarumSansBitmap( 0xF0110..0xF012F, // SHEET_DEVANAGARI2_INTERNAL_VARW 0xF0520..0xF057F, // SHEET_CODESTYLE_ASCII_VARW 0xFB00..0xFB17, // SHEET_ALPHABETIC_PRESENTATION_FORMS + 0x1B000..0x1B16F, // SHEET_HENTAIGANA_VARW ) private val codeRangeHangulCompat = 0x3130..0x318F @@ -2971,7 +2975,6 @@ class TerrarumSansBitmap( private fun runicIndexY(c: CodePoint) = (c - 0x16A0) / 16 private fun kanaIndexY(c: CodePoint) = if (c in 0x31F0..0x31FF) 12 - else if (c in 0x1B000..0x1B00F) 13 else (c - 0x3040) / 16 private fun cjkPunctIndexY(c: CodePoint) = (c - 0x3000) / 16 private fun cyrilicIndexY(c: CodePoint) = (c - 0x400) / 16 @@ -3006,6 +3009,7 @@ class TerrarumSansBitmap( private fun devanagari2IndexY(c: CodePoint) = (c - 0xF0110) / 16 private fun codestyleAsciiIndexY(c: CodePoint) = (c - 0xF0520) / 16 private fun alphabeticPresentationFormsY(c: CodePoint) = (c - 0xFB00) / 16 + private fun hentaiganaIndexY(c: CodePoint) = (c - 0x1B000) / 16 val charsetOverrideDefault = Character.toChars(CHARSET_OVERRIDE_DEFAULT).toSurrogatedString() val charsetOverrideBulgarian = Character.toChars(CHARSET_OVERRIDE_BG_BG).toSurrogatedString() diff --git a/width_bit_encoding_annotated.png b/width_bit_encoding_annotated.png index 18806e5..4c8ef4c 100755 Binary files a/width_bit_encoding_annotated.png and b/width_bit_encoding_annotated.png differ diff --git a/work_files/hentaigana_variable.kra b/work_files/hentaigana_variable.kra index 591eded..2906378 100644 --- a/work_files/hentaigana_variable.kra +++ b/work_files/hentaigana_variable.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:959646a29e7758a46103fbcfc43aeddbd9c4bfbc368d5d00d61bbb80a0d28849 -size 117220 +oid sha256:c40f1dec1f2f95fc112cad910feb5f6482442ee9ce56fa102207ed0e79e05e2f +size 163156