diff --git a/assets/LatinExtA_variable.tga b/assets/LatinExtA_variable.tga index b4186bf..3361f3d 100644 Binary files a/assets/LatinExtA_variable.tga and b/assets/LatinExtA_variable.tga differ diff --git a/assets/hangul_johab.tga b/assets/hangul_johab.tga index 7ab063f..64b3207 100644 Binary files a/assets/hangul_johab.tga and b/assets/hangul_johab.tga differ diff --git a/assets/kartuli_variable.tga b/assets/kartuli_variable.tga index c2d6834..4dbead6 100644 Binary files a/assets/kartuli_variable.tga and b/assets/kartuli_variable.tga differ diff --git a/demo/.idea/workspace.xml b/demo/.idea/workspace.xml index 551a9c0..9aa6736 100644 --- a/demo/.idea/workspace.xml +++ b/demo/.idea/workspace.xml @@ -5,9 +5,6 @@ - - - @@ -23,62 +20,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -141,8 +112,6 @@ - - @@ -189,13 +158,15 @@ + + - + @@ -413,23 +384,24 @@ - + + - + - + - + @@ -438,7 +410,6 @@ - @@ -450,7 +421,9 @@ - + + @@ -463,7 +436,43 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -480,9 +489,7 @@ - - - + @@ -491,7 +498,7 @@ - + @@ -501,7 +508,7 @@ - + @@ -518,9 +525,7 @@ - - - + @@ -529,7 +534,7 @@ - + @@ -539,7 +544,7 @@ - + @@ -548,9 +553,7 @@ - - - + @@ -567,7 +570,7 @@ - + @@ -577,7 +580,7 @@ - + @@ -587,7 +590,7 @@ - + @@ -596,9 +599,7 @@ - - - + @@ -607,7 +608,7 @@ - + @@ -617,7 +618,7 @@ - + @@ -641,9 +642,7 @@ - - - + @@ -669,6 +668,14 @@ + + + + + + + + @@ -677,32 +684,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - + + - - - - - - - - - - - + @@ -731,7 +752,7 @@ - Kotlin + Detection - TerrarumSansDemo + Kotlin|TerrarumSansDemo diff --git a/demo/TerrarumSansDemo.iml b/demo/TerrarumSansDemo.iml index ab1490a..a66d395 100644 --- a/demo/TerrarumSansDemo.iml +++ b/demo/TerrarumSansDemo.iml @@ -6,8 +6,9 @@ diff --git a/demo/src/net/torvald/terrarum/imagefont/GameFontBase.kt b/demo/src/net/torvald/terrarum/imagefont/GameFontBase.kt index 83c7b0a..7d0e2b6 100644 --- a/demo/src/net/torvald/terrarum/imagefont/GameFontBase.kt +++ b/demo/src/net/torvald/terrarum/imagefont/GameFontBase.kt @@ -1,27 +1,49 @@ -package net.torvald.imagefont +package net.torvald.terrarumsansbitmap.slick2d -import org.lwjgl.opengl.GL11 -import org.newdawn.slick.* +import org.newdawn.slick.Color +import org.newdawn.slick.Font +import org.newdawn.slick.Image +import org.newdawn.slick.SpriteSheet import org.newdawn.slick.opengl.Texture -import java.nio.ByteOrder +import java.io.BufferedOutputStream +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream import java.util.* +import java.util.zip.GZIPInputStream /** - * Created by minjaesong on 16-01-27. + * LibGDX port of Terrarum Sans Bitmap implementation + * + * Filename and Extension for the spritesheet is hard-coded, which are: + * + * - ascii_variable.tga + * - hangul_johab.tga + * - LatinExtA_variable.tga + * - LatinExtB_variable.tga + * - kana.tga + * - cjkpunct.tga + * - wenquanyi.tga.gz + * - cyrillic_variable.tga + * - fullwidth_forms.tga + * - unipunct_variable.tga + * - greek_variable.tga + * - thai_variable.tga + * - puae000-e0ff.tga + * + * + * Glyphs are drawn lazily (calculated on-the-fly, rather than load up all), which is inevitable as we just can't load + * up 40k+ characters on the machine, which will certainly make loading time painfully long. + * + * @param noShadow Self-explanatory + * @param flipY If you have Y-down coord system implemented on your GDX (e.g. legacy codebase), set this to ```true``` so that the shadow won't be upside-down. For glyph getting upside-down, set ```TextureRegionPack.globalFlipY = true```. + * + * Created by minjaesong on 2017-06-15. */ -open class GameFontBase : Font { - - private fun getHan(hanIndex: Int): IntArray { - val han_x = hanIndex % JONG_COUNT - val han_y = hanIndex / JONG_COUNT - val ret = intArrayOf(han_x, han_y) - return ret - } +class GameFontBase(fontDir: String, val noShadow: Boolean = false) : Font { private fun getHanChosung(hanIndex: Int) = hanIndex / (JUNG_COUNT * JONG_COUNT) - private fun getHanJungseong(hanIndex: Int) = hanIndex / JONG_COUNT % JUNG_COUNT - private fun getHanJongseong(hanIndex: Int) = hanIndex % JONG_COUNT private val jungseongWide = arrayOf(8, 12, 13, 17, 18, 21) @@ -54,18 +76,26 @@ open class GameFontBase : Font { 9 } - private fun isHangul(c: Char) = c.toInt() in 0xAC00..0xD7A3 - private fun isAscii(c: Char) = c.toInt() in 0x20..0xFF - private fun isRunic(c: Char) = runicList.contains(c) - private fun isExtA(c: Char) = c.toInt() in 0x100..0x17F - private fun isExtB(c: Char) = c.toInt() in 0x180..0x24F - private fun isKana(c: Char) = c.toInt() in 0x3040..0x30FF - private fun isCJKPunct(c: Char) = c.toInt() in 0x3000..0x303F - private fun isUniHan(c: Char) = c.toInt() in 0x3400..0x9FFF - private fun isCyrilic(c: Char) = c.toInt() in 0x400..0x45F - private fun isFullwidthUni(c: Char) = c.toInt() in 0xFF00..0xFF1F - private fun isUniPunct(c: Char) = c.toInt() in 0x2000..0x206F - private fun isGreek(c: Char) = c.toInt() in 0x370..0x3CE + private fun isHangul(c: Char) = c.toInt() in codeRange[SHEET_HANGUL] + private fun isAscii(c: Char) = c.toInt() in codeRange[SHEET_ASCII_VARW] + //private fun isRunic(c: Char) = runicList.contains(c) + private fun isExtA(c: Char) = c.toInt() in codeRange[SHEET_EXTA_VARW] + private fun isExtB(c: Char) = c.toInt() in codeRange[SHEET_EXTB_VARW] + private fun isKana(c: Char) = c.toInt() in codeRange[SHEET_KANA] + private fun isCJKPunct(c: Char) = c.toInt() in codeRange[SHEET_CJK_PUNCT] + private fun isUniHan(c: Char) = c.toInt() in codeRange[SHEET_UNIHAN] + private fun isCyrilic(c: Char) = c.toInt() in codeRange[SHEET_CYRILIC_VARW] + private fun isFullwidthUni(c: Char) = c.toInt() in codeRange[SHEET_FW_UNI] + private fun isUniPunct(c: Char) = c.toInt() in codeRange[SHEET_UNI_PUNCT] + private fun isGreek(c: Char) = c.toInt() in codeRange[SHEET_GREEK_VARW] + private fun isThai(c: Char) = c.toInt() in codeRange[SHEET_THAI_VARW] + private fun isDiacritics(c: Char) = c.toInt() in 0xE34..0xE3A + || c.toInt() in 0xE47..0xE4E + || c.toInt() == 0xE31 + private fun isCustomSym(c: Char) = c.toInt() in codeRange[SHEET_CUSTOM_SYM] + private fun isArmenian(c: Char) = c.toInt() in codeRange[SHEET_HAYEREN_VARW] + private fun isKartvelian(c: Char) = c.toInt() in codeRange[SHEET_KARTULI_VARW] + private fun isIPA(c: Char) = c.toInt() in codeRange[SHEET_IPA_VARW] @@ -75,8 +105,8 @@ open class GameFontBase : Font { private fun extBindexX(c: Char) = (c.toInt() - 0x180) % 16 private fun extBindexY(c: Char) = (c.toInt() - 0x180) / 16 - private fun runicIndexX(c: Char) = runicList.indexOf(c) % 16 - private fun runicIndexY(c: Char) = runicList.indexOf(c) / 16 + //private fun runicIndexX(c: Char) = runicList.indexOf(c) % 16 + //private fun runicIndexY(c: Char) = runicList.indexOf(c) / 16 private fun kanaIndexX(c: Char) = (c.toInt() - 0x3040) % 16 private fun kanaIndexY(c: Char) = (c.toInt() - 0x3040) / 16 @@ -84,9 +114,6 @@ open class GameFontBase : Font { private fun cjkPunctIndexX(c: Char) = (c.toInt() - 0x3000) % 16 private fun cjkPunctIndexY(c: Char) = (c.toInt() - 0x3000) / 16 - private fun unihanIndexX(c: Char) = (c.toInt() - 0x3400) % 256 - private fun unihanIndexY(c: Char) = (c.toInt() - 0x3400) / 256 - private fun cyrilicIndexX(c: Char) = (c.toInt() - 0x400) % 16 private fun cyrilicIndexY(c: Char) = (c.toInt() - 0x400) / 16 @@ -96,88 +123,244 @@ open class GameFontBase : Font { private fun uniPunctIndexX(c: Char) = (c.toInt() - 0x2000) % 16 private fun uniPunctIndexY(c: Char) = (c.toInt() - 0x2000) / 16 + private fun unihanIndexX(c: Char) = (c.toInt() - 0x3400) % 256 + private fun unihanIndexY(c: Char) = (c.toInt() - 0x3400) / 256 + private fun greekIndexX(c: Char) = (c.toInt() - 0x370) % 16 private fun greekIndexY(c: Char) = (c.toInt() - 0x370) / 16 + private fun thaiIndexX(c: Char) = (c.toInt() - 0xE00) % 16 + private fun thaiIndexY(c: Char) = (c.toInt() - 0xE00) / 16 + + private fun symbolIndexX(c: Char) = (c.toInt() - 0xE000) % 16 + private fun symbolIndexY(c: Char) = (c.toInt() - 0xE000) / 16 + + private fun armenianIndexX(c: Char) = (c.toInt() - 0x530) % 16 + private fun armenianIndexY(c: Char) = (c.toInt() - 0x530) / 16 + + private fun kartvelianIndexX(c: Char) = (c.toInt() - 0x10D0) % 16 + private fun kartvelianIndexY(c: Char) = (c.toInt() - 0x10D0) / 16 + + private fun ipaIndexX(c: Char) = (c.toInt() - 0x250) % 16 + private fun ipaIndexY(c: Char) = (c.toInt() - 0x250) / 16 + private val unihanWidthSheets = arrayOf( SHEET_UNIHAN, - SHEET_FW_UNI, - SHEET_UNIHAN - ) - private val zeroWidthSheets = arrayOf( - SHEET_COLOURCODE + SHEET_FW_UNI ) private val variableWidthSheets = arrayOf( SHEET_ASCII_VARW, - SHEET_CYRILIC_VARW, SHEET_EXTA_VARW, + SHEET_EXTB_VARW, + SHEET_CYRILIC_VARW, + SHEET_UNI_PUNCT, SHEET_GREEK_VARW, - SHEET_EXTB_VARW + SHEET_THAI_VARW, + SHEET_HAYEREN_VARW, + SHEET_KARTULI_VARW, + SHEET_IPA_VARW ) + private val fontParentDir = if (fontDir.endsWith('/') || fontDir.endsWith('\\')) fontDir else "$fontDir/" + private val fileList = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!! + "ascii_variable.tga", + "hangul_johab.tga", + "LatinExtA_variable.tga", + "LatinExtB_variable.tga", + "kana.tga", + "cjkpunct.tga", + "wenquanyi.tga.gz", + "cyrilic_variable.tga", + "fullwidth_forms.tga", + "unipunct_variable.tga", + "greek_variable.tga", + "thai_variable.tga", + "hayeren_variable.tga", + "kartuli_variable.tga", + "ipa_ext_variable.tga", + "puae000-e0ff.tga" + ) + private val cyrilic_bg = "cyrilic_bulgarian_variable.tga" + private val cyrilic_sr = "cyrilic_serbian_variable.tga" + private val codeRange = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!! + 0..0xFF, + 0xAC00..0xD7A3, + 0x100..0x17F, + 0x180..0x24F, + 0x3040..0x30FF, + 0x3000..0x303F, + 0x3400..0x9FFF, + 0x400..0x52F, + 0xFF00..0xFF1F, + 0x2000..0x205F, + 0x370..0x3CE, + 0xE00..0xE5F, + 0x530..0x58F, + 0x10D0..0x10FF, + 0x250..0x2AF, + 0xE000..0xE0FF + ) + private val glyphWidths: HashMap = HashMap() // if the value is negative, it's diacritics + private val sheets: Array - override fun getWidth(s: String) = getWidthSubstr(s, s.length) - private fun getWidthSubstr(s: String, endIndex: Int): Int { - var len = 0 - for (i in 0..endIndex - 1) { - val chr = s[i] - val ctype = getSheetType(s[i]) + init { + val sheetsPack = ArrayList() - if (variableWidthSheets.contains(ctype)) { - len += try { - asciiWidths[chr.toInt()]!! - } - catch (e: kotlin.KotlinNullPointerException) { - println("KotlinNullPointerException on glyph number ${Integer.toHexString(chr.toInt()).toUpperCase()}") - //System.exit(1) - W_LATIN_WIDE // failsafe - } + // first we create pixmap to read pixels, then make texture using pixmap + fileList.forEachIndexed { index, it -> + val isVariable1 = it.endsWith("_variable.tga") + val isVariable2 = variableWidthSheets.contains(index) + val isVariable = isVariable1 && isVariable2 + + // idiocity check + if (isVariable1 && !isVariable2) + throw Error("[TerrarumSansBitmap] font is named as variable on the name but not enlisted as") + else if (!isVariable1 && isVariable2) + throw Error("[TerrarumSansBitmap] font is enlisted as variable on the name but not named as") + + + val image: Image + + + // unpack gz if applicable + if (it.endsWith(".gz")) { + val gzi = GZIPInputStream(FileInputStream(fontParentDir + it)) + val wholeFile = gzi.readBytes() + gzi.close() + val fos = BufferedOutputStream(FileOutputStream("tmp_wenquanyi.tga")) + fos.write(wholeFile) + fos.flush() + fos.close() + + image = Image("tmp_wenquanyi.tga") + + File("tmp_wenquanyi.tga").delete() + } + else { + image = Image(fontParentDir + it) } - else if (zeroWidthSheets.contains(ctype)) - len += 0 - else if (ctype == SHEET_CJK_PUNCT) - len += W_ASIAN_PUNCT - else if (ctype == SHEET_HANGUL) - len += W_HANGUL - else if (ctype == SHEET_KANA) - len += W_KANA - else if (unihanWidthSheets.contains(ctype)) - len += W_UNIHAN - else - len += W_LATIN_WIDE - if (i < endIndex - 1) len += interchar + val texture = image.texture + + if (isVariable) { + println("[TerrarumSansBitmap] loading texture $it [VARIABLE]") + buildWidthTable(texture, codeRange[index], 16) + } + else { + println("[TerrarumSansBitmap] loading texture $it") + } + + val texRegPack = if (isVariable) { + SpriteSheet(image, W_VAR_INIT, H - 1, HGAP_VAR) + } + else if (index == SHEET_UNIHAN) { + SpriteSheet(image, W_UNIHAN, H_UNIHAN) // the only exception that is height is 16 + } + // below they all have height of 20 'H' + else if (index == SHEET_FW_UNI) { + SpriteSheet(image, W_UNIHAN, H) + } + else if (index == SHEET_CJK_PUNCT) { + SpriteSheet(image, W_ASIAN_PUNCT, H) + } + else if (index == SHEET_KANA) { + SpriteSheet(image, W_KANA, H) + } + else if (index == SHEET_HANGUL) { + SpriteSheet(image, W_HANGUL, H) + } + else if (index == SHEET_CUSTOM_SYM) { + SpriteSheet(image, SIZE_CUSTOM_SYM, SIZE_CUSTOM_SYM) // TODO variable + } + else throw IllegalArgumentException("[TerrarumSansBitmap] Unknown sheet index: $index") + + + sheetsPack.add(texRegPack) } - return len * scale + + sheets = sheetsPack.toTypedArray() } - override fun getHeight(s: String) = H * scale + private var localeBuffer = "" - override fun getLineHeight() = H * scale + fun reload(locale: String) { + if (!localeBuffer.startsWith("ru") && locale.startsWith("ru")) { + val image = Image(fontParentDir + fileList[SHEET_CYRILIC_VARW]) + sheets[SHEET_CYRILIC_VARW].destroy() + sheets[SHEET_CYRILIC_VARW] = SpriteSheet(image, W_VAR_INIT, H, HGAP_VAR, 0) + } + else if (!localeBuffer.startsWith("bg") && locale.startsWith("bg")) { + val image = Image(fontParentDir + cyrilic_bg) + sheets[SHEET_CYRILIC_VARW].destroy() + sheets[SHEET_CYRILIC_VARW] = SpriteSheet(image, W_VAR_INIT, H, HGAP_VAR, 0) + } + else if (!localeBuffer.startsWith("sr") && locale.startsWith("sr")) { + val image = Image(fontParentDir + cyrilic_sr) + sheets[SHEET_CYRILIC_VARW].destroy() + sheets[SHEET_CYRILIC_VARW] = SpriteSheet(image, W_VAR_INIT, H, HGAP_VAR, 0) + } - override fun drawString(x: Float, y: Float, s: String) = drawString(x, y, s, Color.white) + localeBuffer = locale + } - override fun drawString(x: Float, y: Float, s: String, color: Color) { - GL11.glEnable(GL11.GL_BLEND) - GL11.glColorMask(true, true, true, true) - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA) + override fun getLineHeight(): Int = H + override fun getHeight(p0: String) = lineHeight - var thisCol = color - // hangul fonts first - //hangulSheet.startUse() // disabling texture binding to make the font coloured - // JOHAB - for (i in 0..s.length - 1) { - val ch = s[i] - if (ch.isColourCode()) { - thisCol = colourKey[ch]!! - continue - } - if (isHangul(ch)) { - val hIndex = ch.toInt() - 0xAC00 + private val offsetUnihan = (H - H_UNIHAN) / 2 + private val offsetCustomSym = (H - SIZE_CUSTOM_SYM) / 2 + + private var textBuffer: CharSequence = "" + private var textBWidth = intArrayOf() // absolute posX of glyphs from print-origin + private var textBGSize = intArrayOf() // width of each glyph + + override fun drawString(x: Float, y: Float, str: String) { + drawString(x, y, str, Color.white) + } + + override fun drawString(p0: Float, p1: Float, p2: String?, p3: Color?, p4: Int, p5: Int) { + throw UnsupportedOperationException() + } + + override fun drawString(x: Float, y: Float, str: String, color: Color) { + if (textBuffer != str) { + textBuffer = str + val widths = getWidthOfCharSeq(str) + + textBGSize = widths + + textBWidth = IntArray(str.length, { charIndex -> + if (charIndex == 0) + 0 + else { + var acc = 0 + (0..charIndex - 1).forEach { acc += maxOf(0, widths[it]) } // don't accumulate diacrtics (which has negative value) + /*return*/acc + } + }) + } + + + //print("[TerrarumSansBitmap] widthTable for $textBuffer: ") + //textBWidth.forEach { print("$it ") }; println() + + + val mainCol = color + val shadowCol = color.darker(0.5f) + + + textBuffer.forEachIndexed { index, c -> + val sheetID = getSheetType(c) + val sheetXY = getSheetwisePosition(c) + + //println("[TerrarumSansBitmap] sprite: $sheetID:${sheetXY[0]}x${sheetXY[1]}") + + if (sheetID == SHEET_HANGUL) { + val hangulSheet = sheets[SHEET_HANGUL] + val hIndex = c.toInt() - 0xAC00 val indexCho = getHanChosung(hIndex) val indexJung = getHanJungseong(hIndex) @@ -187,133 +370,123 @@ open class GameFontBase : Font { val jungRow = getHanMedialRow(hIndex) val jongRow = getHanFinalRow(hIndex) - val glyphW = getWidth(ch.toString()) - hangulSheet.getSubImage(indexCho, choRow).drawWithShadow( - Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), - Math.round(y).toFloat(), - scale.toFloat(), thisCol - ) - hangulSheet.getSubImage(indexJung, jungRow).drawWithShadow( - Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), - Math.round(y).toFloat(), - scale.toFloat(), thisCol - ) - hangulSheet.getSubImage(indexJong, jongRow).drawWithShadow( - Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), - Math.round(y).toFloat(), - scale.toFloat(), thisCol - ) - } - } - //hangulSheet.endUse() + if (!noShadow) { + hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index] + 1, y, shadowCol) + hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index] , y, shadowCol) + hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index] + 1, y, shadowCol) - // WenQuanYi - //uniHan.startUse() + hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index] + 1, y, shadowCol) + hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index] , y, shadowCol) + hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index] + 1, y, shadowCol) - for (i in 0..s.length - 1) { - val ch = s[i] - - if (ch.isColourCode()) { - thisCol = colourKey[ch]!! - continue - } - - if (isUniHan(ch)) { - val glyphW = getWidth("" + ch) - uniHan.getSubImage(unihanIndexX(ch), unihanIndexY(ch)).drawWithShadow( - Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), - Math.round((H - H_UNIHAN) / 2 + y).toFloat(), - scale.toFloat(), thisCol - ) - } - } - - //uniHan.endUse() - - // regular fonts - var prevInstance = -1 - for (i in 0..s.length - 1) { - val ch = s[i] - - if (ch.isColourCode()) { - thisCol = colourKey[ch]!! - continue - } - - if (!isHangul(ch) && !isUniHan(ch)) { - - // if not init, endUse first - if (prevInstance != -1) { - //sheetKey[prevInstance].endUse() - } - //sheetKey[getSheetType(ch)].startUse() - prevInstance = getSheetType(ch) - - val sheetX: Int - val sheetY: Int - when (prevInstance) { - SHEET_EXTA_VARW -> { - sheetX = extAindexX(ch) - sheetY = extAindexY(ch) - } - SHEET_EXTB_VARW -> { - sheetX = extBindexX(ch) - sheetY = extBindexY(ch) - } - SHEET_KANA -> { - sheetX = kanaIndexX(ch) - sheetY = kanaIndexY(ch) - } - SHEET_CJK_PUNCT -> { - sheetX = cjkPunctIndexX(ch) - sheetY = cjkPunctIndexY(ch) - } - SHEET_CYRILIC_VARW -> { - sheetX = cyrilicIndexX(ch) - sheetY = cyrilicIndexY(ch) - } - SHEET_FW_UNI -> { - sheetX = fullwidthUniIndexX(ch) - sheetY = fullwidthUniIndexY(ch) - } - SHEET_UNI_PUNCT -> { - sheetX = uniPunctIndexX(ch) - sheetY = uniPunctIndexY(ch) - } - SHEET_GREEK_VARW -> { - sheetX = greekIndexX(ch) - sheetY = greekIndexY(ch) - } - else -> { - sheetX = ch.toInt() % 16 - sheetY = ch.toInt() / 16 - } + hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index] + 1, y, shadowCol) + hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index] , y, shadowCol) + hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index] + 1, y, shadowCol) } - val glyphW = getWidth("" + ch) + + hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index], y, mainCol) + hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index], y, mainCol) + hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index], y, mainCol) + } + else { try { - sheetKey[prevInstance]!!.getSubImage(sheetX, sheetY).drawWithShadow( - Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(), - Math.round(y).toFloat(), - scale.toFloat(), thisCol + val offset = if (!isDiacritics(c)) 0 else { + if (index > 0) // LIMITATION: does not support double (or more) diacritics properly + (textBGSize[index] - textBGSize[index - 1]) / 2 + else + textBGSize[index] + } + + if (!noShadow) { + sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw( + x + textBWidth[index] + 1 + offset, + y + (if (sheetID == SHEET_UNIHAN) // evil exceptions + offsetUnihan + else if (sheetID == SHEET_CUSTOM_SYM) + offsetCustomSym + else + 0), + shadowCol + ) + sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw( + x + textBWidth[index] + offset, + y + (if (sheetID == SHEET_UNIHAN) // evil exceptions + offsetUnihan + 1 + else if (sheetID == SHEET_CUSTOM_SYM) + offsetCustomSym + 1 + else + 1), + shadowCol + ) + sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw( + x + textBWidth[index] + 1 + offset, + y + (if (sheetID == SHEET_UNIHAN) // evil exceptions + offsetUnihan + 1 + else if (sheetID == SHEET_CUSTOM_SYM) + offsetCustomSym + 1 + else + 1), + shadowCol + ) + } + + + sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw( + x + textBWidth[index] + offset, + y + if (sheetID == SHEET_UNIHAN) // evil exceptions + offsetUnihan + else if (sheetID == SHEET_CUSTOM_SYM) + offsetCustomSym + else 0, + mainCol ) } - catch (e: ArrayIndexOutOfBoundsException) { - // character that does not exist in the sheet. No render, pass. - } - catch (e1: RuntimeException) { - // System.err.println("[GameFontBase] RuntimeException raised while processing character '$ch' (U+${Integer.toHexString(ch.toInt()).toUpperCase()})") - // e1.printStackTrack() + catch (noSuchGlyph: ArrayIndexOutOfBoundsException) { } } - - } - if (prevInstance != -1) { - //sheetKey[prevInstance].endUse() } - GL11.glEnd() + } + + + fun dispose() { + sheets.forEach { it.destroy() } + } + + private fun getWidthOfCharSeq(s: CharSequence): IntArray { + val len = IntArray(s.length) + for (i in 0..s.lastIndex) { + val chr = s[i] + val ctype = getSheetType(s[i]) + + if (variableWidthSheets.contains(ctype)) { + if (!glyphWidths.containsKey(chr.toInt())) { + println("[TerrarumSansBitmap] no width data for glyph number ${Integer.toHexString(chr.toInt()).toUpperCase()}") + len[i] = W_LATIN_WIDE + } + + len[i] = glyphWidths[chr.toInt()]!! + } + else if (ctype == SHEET_CJK_PUNCT) + len[i] = W_ASIAN_PUNCT + else if (ctype == SHEET_HANGUL) + len[i] = W_HANGUL + else if (ctype == SHEET_KANA) + len[i] = W_KANA + else if (unihanWidthSheets.contains(ctype)) + len[i] = W_UNIHAN + else if (ctype == SHEET_CUSTOM_SYM) + len[i] = SIZE_CUSTOM_SYM + else + len[i] = W_LATIN_WIDE + + if (scale > 1) len[i] *= scale + + if (i < s.lastIndex) len[i] += interchar + } + return len } private fun getSheetType(c: Char): Int { @@ -339,112 +512,128 @@ open class GameFontBase : Font { return SHEET_FW_UNI else if (isGreek(c)) return SHEET_GREEK_VARW - else if (c.isColourCode()) - return SHEET_COLOURCODE + else if (isThai(c)) + return SHEET_THAI_VARW + else if (isCustomSym(c)) + return SHEET_CUSTOM_SYM + else if (isArmenian(c)) + return SHEET_HAYEREN_VARW + else if (isKartvelian(c)) + return SHEET_KARTULI_VARW + else if (isIPA(c)) + return SHEET_IPA_VARW else - return SHEET_UNKNOWN// fixed width punctuations + return SHEET_UNKNOWN // fixed width // fallback } - /** - * Draw part of a string to the screen. Note that this will still position the text as though - * it's part of the bigger string. - * @param x - * * - * @param y - * * - * @param s - * * - * @param color - * * - * @param startIndex - * * - * @param endIndex - */ - override fun drawString(x: Float, y: Float, s: String, color: Color, startIndex: Int, endIndex: Int) { - val unprintedHead = s.substring(0, startIndex) - val printedBody = s.substring(startIndex, endIndex) - val xoff = getWidth(unprintedHead) - drawString(x + xoff, y, printedBody, color) - } - - fun Char.isColourCode() = colourKey.containsKey(this) - - fun buildWidthTable(sheet: SpriteSheet, codeOffset: Int, codeRange: IntRange, rows: Int = 16) { - fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this) - - /** @return Intarray(R, G, B, A) */ - fun Texture.getPixel(x: Int, y: Int): IntArray { - val textureWidth = this.textureWidth - val hasAlpha = this.hasAlpha() - - val offset = (if (hasAlpha) 4 else 3) * (textureWidth * y + x) // 4: # of channels (RGBA) - - if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) { - return intArrayOf( - this.textureData[offset].toUint(), - this.textureData[offset + 1].toUint(), - this.textureData[offset + 2].toUint(), - if (hasAlpha) - this.textureData[offset + 3].toUint() - else 255 - ) + private fun getSheetwisePosition(ch: Char): IntArray { + val sheetX: Int; val sheetY: Int + when (getSheetType(ch)) { + SHEET_UNIHAN -> { + sheetX = unihanIndexX(ch) + sheetY = unihanIndexY(ch) } - else { - return intArrayOf( - this.textureData[offset + 2].toUint(), - this.textureData[offset + 1].toUint(), - this.textureData[offset].toUint(), - if (hasAlpha) - this.textureData[offset + 3].toUint() - else 255 - ) + SHEET_EXTA_VARW -> { + sheetX = extAindexX(ch) + sheetY = extAindexY(ch) + } + SHEET_EXTB_VARW -> { + sheetX = extBindexX(ch) + sheetY = extBindexY(ch) + } + SHEET_KANA -> { + sheetX = kanaIndexX(ch) + sheetY = kanaIndexY(ch) + } + SHEET_CJK_PUNCT -> { + sheetX = cjkPunctIndexX(ch) + sheetY = cjkPunctIndexY(ch) + } + SHEET_CYRILIC_VARW -> { + sheetX = cyrilicIndexX(ch) + sheetY = cyrilicIndexY(ch) + } + SHEET_FW_UNI -> { + sheetX = fullwidthUniIndexX(ch) + sheetY = fullwidthUniIndexY(ch) + } + SHEET_UNI_PUNCT -> { + sheetX = uniPunctIndexX(ch) + sheetY = uniPunctIndexY(ch) + } + SHEET_GREEK_VARW -> { + sheetX = greekIndexX(ch) + sheetY = greekIndexY(ch) + } + SHEET_THAI_VARW -> { + sheetX = thaiIndexX(ch) + sheetY = thaiIndexY(ch) + } + SHEET_CUSTOM_SYM -> { + sheetX = symbolIndexX(ch) + sheetY = symbolIndexY(ch) + } + SHEET_HAYEREN_VARW -> { + sheetX = armenianIndexX(ch) + sheetY = armenianIndexY(ch) + } + SHEET_KARTULI_VARW -> { + sheetX = kartvelianIndexX(ch) + sheetY = kartvelianIndexY(ch) + } + SHEET_IPA_VARW -> { + sheetX = ipaIndexX(ch) + sheetY = ipaIndexY(ch) + } + else -> { + sheetX = ch.toInt() % 16 + sheetY = ch.toInt() / 16 } } - val binaryCodeOffset = 15 + return intArrayOf(sheetX, sheetY) + } - val cellW = sheet.getSubImage(0, 0).width + 1 // should be 16 - val cellH = sheet.getSubImage(0, 0).height + 1 // should be 20 + fun buildWidthTable(texture: Texture, codeRange: IntRange, cols: Int = 16) { + val binaryCodeOffset = W_VAR_INIT - // control chars - for (ccode in codeRange) { - val glyphX = ccode % rows - val glyphY = ccode / rows + val cellW = W_VAR_INIT + 1 + val cellH = H - val codeStartX = (glyphX * cellW) + binaryCodeOffset - val codeStartY = (glyphY * cellH) + for (code in codeRange) { + + val cellX = ((code - codeRange.start) % cols) * cellW + val cellY = ((code - codeRange.start) / cols) * cellH + + val codeStartX = cellX + binaryCodeOffset + val codeStartY = cellY var glyphWidth = 0 + for (downCtr in 0..3) { - // if alpha is not zero, assume it's 1 - if (sheet.texture.getPixel(codeStartX, codeStartY + downCtr)[3] == 255) { + // if ALPHA is not zero, assume it's 1 + if (texture.textureData[4 * (codeStartX + (codeStartY + downCtr) * texture.textureWidth) + 3] != 0.toByte()) { glyphWidth = glyphWidth or (1 shl downCtr) } } - asciiWidths[codeOffset + ccode] = glyphWidth + val isDiacritics = texture.textureData[4 * (codeStartX + (codeStartY + H - 1) * texture.textureWidth) + 3] != 0.toByte() + if (isDiacritics) + glyphWidth = -glyphWidth + + glyphWidths[code] = glyphWidth } } + + override fun getWidth(text: String): Int { + return getWidthOfCharSeq(text).sum() + } + companion object { - lateinit internal var hangulSheet: SpriteSheet - lateinit internal var asciiSheet: SpriteSheet - - internal val asciiWidths: HashMap = HashMap() - - lateinit internal var extASheet: SpriteSheet - lateinit internal var extBSheet: SpriteSheet - lateinit internal var kanaSheet: SpriteSheet - lateinit internal var cjkPunct: SpriteSheet - lateinit internal var uniHan: SpriteSheet - lateinit internal var cyrilic: SpriteSheet - lateinit internal var fullwidthForms: SpriteSheet - lateinit internal var uniPunct: SpriteSheet - lateinit internal var greekSheet: SpriteSheet - internal val JUNG_COUNT = 21 internal val JONG_COUNT = 28 @@ -453,27 +642,33 @@ open class GameFontBase : Font { internal val W_KANA = 12 internal val W_UNIHAN = 16 internal val W_LATIN_WIDE = 9 // width of regular letters + internal val W_VAR_INIT = 15 + + internal val HGAP_VAR = 1 internal val H = 20 internal val H_UNIHAN = 16 - internal val SHEET_ASCII_VARW = 0 - internal val SHEET_HANGUL = 1 - internal val SHEET_EXTA_VARW = 3 - internal val SHEET_EXTB_VARW = 4 - internal val SHEET_KANA = 5 - internal val SHEET_CJK_PUNCT = 6 - internal val SHEET_UNIHAN = 7 - internal val SHEET_CYRILIC_VARW = 8 - internal val SHEET_FW_UNI = 9 - internal val SHEET_UNI_PUNCT = 10 - internal val SHEET_GREEK_VARW = 11 + internal val SIZE_CUSTOM_SYM = 18 + internal val SHEET_ASCII_VARW = 0 + internal val SHEET_HANGUL = 1 + internal val SHEET_EXTA_VARW = 2 + internal val SHEET_EXTB_VARW = 3 + internal val SHEET_KANA = 4 + internal val SHEET_CJK_PUNCT = 5 + internal val SHEET_UNIHAN = 6 + internal val SHEET_CYRILIC_VARW = 7 + internal val SHEET_FW_UNI = 8 + internal val SHEET_UNI_PUNCT = 9 + internal val SHEET_GREEK_VARW = 10 + internal val SHEET_THAI_VARW = 11 + internal val SHEET_HAYEREN_VARW = 12 + internal val SHEET_KARTULI_VARW = 13 + internal val SHEET_IPA_VARW = 14 + internal val SHEET_CUSTOM_SYM = 15 internal val SHEET_UNKNOWN = 254 - internal val SHEET_COLOURCODE = 255 - - lateinit internal var sheetKey: Array /** * Runic letters list used for game. The set is @@ -491,68 +686,15 @@ open class GameFontBase : Font { * ᛭ᛋᛁᚴᚱᛁᚦᛦ᛭ * ᛭ᛂᛚᛋᛅ᛭ᛏᚱᚢᛏᚾᛁᚾᚴᚢᚾᛅ᛬ᛅᚱᚾᛅᛏᛅᛚᛋ */ - internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ') + //internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ') + // TODO expand to full Unicode runes - internal var interchar = 0 - internal var scale = 1 + var interchar = 0 + var scale = 1 set(value) { if (value > 0) field = value else throw IllegalArgumentException("Font scale cannot be zero or negative (input: $value)") } + } - val colourKey = hashMapOf( - Pair(0x10.toChar(), Color(0xFFFFFF)), //*w hite - Pair(0x11.toChar(), Color(0xFFE080)), //*y ellow - Pair(0x12.toChar(), Color(0xFFB020)), //o range - Pair(0x13.toChar(), Color(0xFF8080)), //*r ed - Pair(0x14.toChar(), Color(0xFFA0E0)), //f uchsia - Pair(0x15.toChar(), Color(0xE0A0FF)), //*m agenta (purple) - Pair(0x16.toChar(), Color(0x8080FF)), //*b lue - Pair(0x17.toChar(), Color(0x80FFFF)), //c yan - Pair(0x18.toChar(), Color(0x80FF80)), //*g reen - Pair(0x19.toChar(), Color(0x008000)), //v iridian - Pair(0x1A.toChar(), Color(0x805030)), //x (khaki) - Pair(0x1B.toChar(), Color(0x808080)) //*k - //* marked: commonly used - ) - val colToCode = hashMapOf( - Pair("w", 0x10.toChar()), - Pair("y", 0x11.toChar()), - Pair("o", 0x12.toChar()), - Pair("r", 0x13.toChar()), - Pair("f", 0x14.toChar()), - Pair("m", 0x15.toChar()), - Pair("b", 0x16.toChar()), - Pair("c", 0x17.toChar()), - Pair("g", 0x18.toChar()), - Pair("v", 0x19.toChar()), - Pair("x", 0x1A.toChar()), - Pair("k", 0x1B.toChar()) - ) - val codeToCol = hashMapOf( - Pair("w", colourKey[0x10.toChar()]), - Pair("y", colourKey[0x11.toChar()]), - Pair("o", colourKey[0x12.toChar()]), - Pair("r", colourKey[0x13.toChar()]), - Pair("f", colourKey[0x14.toChar()]), - Pair("m", colourKey[0x15.toChar()]), - Pair("b", colourKey[0x16.toChar()]), - Pair("c", colourKey[0x17.toChar()]), - Pair("g", colourKey[0x18.toChar()]), - Pair("v", colourKey[0x19.toChar()]), - Pair("x", colourKey[0x1A.toChar()]), - Pair("k", colourKey[0x1B.toChar()]) - ) - }// end of companion object -} - -fun Image.drawWithShadow(x: Float, y: Float, color: Color) = - this.drawWithShadow(x, y, 1f, color) - -fun Image.drawWithShadow(x: Float, y: Float, scale: Float, color: Color) { - this.draw(x + 1, y + 1, scale, color.darker(0.5f)) - this.draw(x , y + 1, scale, color.darker(0.5f)) - this.draw(x + 1, y , scale, color.darker(0.5f)) - - this.draw(x, y, scale, color) -} +} \ No newline at end of file diff --git a/demo/src/net/torvald/terrarum/imagefont/GameFontDemo.kt b/demo/src/net/torvald/terrarum/imagefont/GameFontDemo.kt index 016a03c..477f4b2 100644 --- a/demo/src/net/torvald/terrarum/imagefont/GameFontDemo.kt +++ b/demo/src/net/torvald/terrarum/imagefont/GameFontDemo.kt @@ -1,6 +1,6 @@ package net.torvald.terrarum.imagefont -import net.torvald.imagefont.GameFontImpl +import net.torvald.terrarumsansbitmap.slick2d.GameFontBase import org.newdawn.slick.* import java.io.File import java.io.FileInputStream @@ -17,10 +17,11 @@ class GameFontDemo : BasicGame("Terrarum Sans Bitmap Demo") { lateinit var gameFont: Font override fun init(p0: GameContainer?) { - gameFont = GameFontImpl() + gameFont = GameFontBase("assets/") } override fun update(gc: GameContainer, delta: Int) { + appgc!!.setTitle("Terrarum Sans Bitmap — F: ${gc.fps}") } override fun render(gc: GameContainer, g: Graphics) { @@ -67,6 +68,8 @@ class GameFontDemo : BasicGame("Terrarum Sans Bitmap Demo") { } } +var appgc: AppGameContainer? = null + fun main(args: Array) { System.setProperty("java.library.path", "lib") @@ -76,17 +79,17 @@ fun main(args: Array) { val HEIGHT = 800 try { - val appgc = AppGameContainer(GameFontDemo()) - appgc.setDisplayMode(WIDTH, HEIGHT, false) + appgc = AppGameContainer(GameFontDemo()) + appgc!!.setDisplayMode(WIDTH, HEIGHT, false) - appgc.setMultiSample(0) - appgc.setShowFPS(false) + appgc!!.setMultiSample(0) + appgc!!.setShowFPS(false) // game will run normally even if it is not focused - appgc.setUpdateOnlyWhenVisible(false) - appgc.alwaysRender = true + appgc!!.setUpdateOnlyWhenVisible(false) + appgc!!.alwaysRender = true - appgc.start() + appgc!!.start() } catch (ex: Exception) { ex.printStackTrace() diff --git a/demo/src/net/torvald/terrarum/imagefont/GameFontImpl.kt b/demo/src/net/torvald/terrarum/imagefont/GameFontImpl.kt deleted file mode 100644 index da08a7b..0000000 --- a/demo/src/net/torvald/terrarum/imagefont/GameFontImpl.kt +++ /dev/null @@ -1,73 +0,0 @@ -package net.torvald.imagefont - -import net.torvald.terrarum.imagefont.GameFontDemo -import org.newdawn.slick.* - -/** - * Created by minjaesong on 16-01-20. - */ -class GameFontImpl : GameFontBase() { - - init { - - GameFontBase.hangulSheet = SpriteSheet( - "./assets/graphics/fonts/hangul_johab.tga", GameFontBase.W_HANGUL, GameFontBase.H) - GameFontBase.asciiSheet = SpriteSheet( - "./assets/graphics/fonts/ascii_variable.tga", 15, 19, 1) - GameFontBase.extASheet = SpriteSheet( - "./assets/graphics/fonts/LatinExtA_variable.tga", 15, 19, 1) - GameFontBase.extBSheet = SpriteSheet( - "./assets/graphics/fonts/LatinExtB_variable.tga", 15, 19, 1) - GameFontBase.kanaSheet = SpriteSheet( - "./assets/graphics/fonts/kana.tga", GameFontBase.W_KANA, GameFontBase.H) - GameFontBase.cjkPunct = SpriteSheet( - "./assets/graphics/fonts/cjkpunct.tga", GameFontBase.W_ASIAN_PUNCT, GameFontBase.H) - GameFontBase.cyrilic = SpriteSheet( - when (GameFontDemo.gameLocale.substring(0..1)) { - "bg" -> "./assets/graphics/fonts/cyrilic_bulgarian_variable.tga" - "sr" -> "./assets/graphics/fonts/cyrilic_serbian_variable.tga" - else -> "./assets/graphics/fonts/cyrilic_variable.tga" - }, 15, 19, 1) - GameFontBase.fullwidthForms = SpriteSheet( - "./assets/graphics/fonts/fullwidth_forms.tga", GameFontBase.W_UNIHAN, GameFontBase.H_UNIHAN) - GameFontBase.uniPunct = SpriteSheet( - "./assets/graphics/fonts/unipunct.tga", GameFontBase.W_LATIN_WIDE, GameFontBase.H) - GameFontBase.uniHan = SpriteSheet( - "./assets/graphics/fonts/wenquanyi.tga", 16, 16) - GameFontBase.greekSheet = SpriteSheet( - "./assets/graphics/fonts/greek_variable.tga", 15, 19, 1) - - val shk = arrayOf( - GameFontBase.asciiSheet, - GameFontBase.hangulSheet, - null, // here was customised runic sheet - GameFontBase.extASheet, - GameFontBase.extBSheet, - GameFontBase.kanaSheet, - GameFontBase.cjkPunct, - GameFontBase.uniHan, - GameFontBase.cyrilic, - GameFontBase.fullwidthForms, - GameFontBase.uniPunct, - GameFontBase.greekSheet - ) - GameFontBase.sheetKey = shk - - - buildWidthTable(asciiSheet, 0, 0..0xFF) - buildWidthTable(extASheet, 0x100, 0..0x7F) - buildWidthTable(extBSheet, 0x180, 0..0xCF) - buildWidthTable(cyrilic, 0x400, 0..0x5F) - buildWidthTable(greekSheet, 0x370, 0..0x5F) - } - - fun reload() { - GameFontBase.cyrilic.destroy() - GameFontBase.cyrilic = SpriteSheet( - when (GameFontDemo.gameLocale.substring(0..1)) { - "bg" -> "./assets/graphics/fonts/cyrilic_bulgarian_variable.tga" - "sr" -> "./assets/graphics/fonts/cyrilic_serbian_variable.tga" - else -> "./assets/graphics/fonts/cyrilic_variable.tga" - }, 15, 19, 1) - } -} diff --git a/demo/text.txt b/demo/text.txt index 9e33850..0aa8a77 100644 --- a/demo/text.txt +++ b/demo/text.txt @@ -1,38 +1,43 @@ -Set locale in config.properties to “bgBG” for alternative Bulgarian letters, “srSR” for Serbian. +x86 се нарича общата микроархитектура на фамилия микропроцесори, основана на Intel 8086. Първите процесори от тази +фамилия, разработени и произвеждани от Intel, са обозначавани с номера, завършващи на 86: 8086, 80186, 80286, 80386 +(впоследствие i386) и 486 (i486). -ABCDEFGHIJKLM NOPQRSTUVWXYZ 12345? -abcdefghijklm nopqrstuvwxyz 67890! +x86 — Intel 8086 prosessorunun arxitekturasının təlimatına əsasən yaradılan prosessor arxitekturası ailəsi. +x86 (= 80x86) – IBM PC-uyumlu kompüterlərdə istifadə olunan Intel mikroprosessorları ailəsi (x = 1, ..., 5 və 8086 +üçün olmaya bilər). Bu ailəyə 086, 186, 286, 386, 486, Pentium, Pentium Pro, Pentium II aiddir. -The bitmap font for game developers who seek good font that has real multilingual support, -for free (as in freedom AND without cost). +Ο όρος x86 αναφέρεται σε μια οικογένεια από αρχιτεκτονικές συνόλου εντολών που βασίζονται στην CPU Intel 8086. +Ο επεξεργαστής 8086 κυκλοφόρησε το 1978 σαν μια πλήρως 16-bit επέκταση του 8080 της Intel που βασιζόταν σε τεχνολογία +8-bit, και εισήγαγε το segmentation για να ξεπεράσει το φράγμα των 16-bit διευθύνσεων της προηγούμενης σχεδίασης. -There are many bitmap fonts on the internet. You care for the multilingual support, but alas! -most of them does not support your language, vector fonts takes too much time to be loaded, -even then their legibility suffers because fuck built-in antialias. -You somehow found a good font, and it makes your game look like a linux terminal, and you say: -“what the fuck? Is this a game or should I rm -rf this shit‽” -You speak Japanese, and you wish to support it, but then このクソなfontは only good for Japanese, -and it is not multilingual, and you don't have a time for this shenanigan. -Eventually you give up, saying “fuck it!” and just use the fonts that do not match well. +x86 또는 80x86은 인텔이 개발한 마이크로프로세서 계열을 부르는 말이자, 이들과 호환되는 프로세서들에서 사용한 명령어 집합 구조들을 통칭하는 +말이다. x86 아키텍처는 데스크톱 컴퓨터 시장에서 매우 널리 쓰이며, PowerPC 같이 좀 더 근대적인 아키텍처를 사용한 프로세서들이 x86과 경쟁했으나 +그다지 많은 시장 점유율을 확보하지는 못했다. -No more suffering. This font has everything you need. +x86(Intel 80x86)-ն ապարատային պլատֆորմ է, որը հանդիսանում է միկրոպրոցեսորի ճարտարապետություն և հրամանների +համապատասխան հավաքածու։ Այն մշակված է և թողարկված, ինչպես Intel-ի, այնպես էլ նրա հետ համատեղելի պրոցեսորների +համար, որոնք ստեղծվել են այլ արտադրողների կողմից։ -while (isVisible(BadFonts)) { ripAndTear(BadFonts).scope(Guts); } -How multilingual? Real multilingual! +Pentium არის კომპანია ინტელის მიერ 1993 წელს გამოშვებული პროცესორი. იგი იყო წარმატებული i486-CPU სერიის +ჩიპების მომდევნო თაობა. Pente (πέντε) – ბერძნული სიტყვაა და ხუთს ნიშნავს. იგი ხომ ინტელის სახლის x86 სერიის +ჩიპების მეხუთე თაობას წარმოადგენდა. -Příliš žluťoučký kůň úpěl ďábelské ódy -Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich -διαφυλάξτε γενικά τη ζωή σας από βαθειά ψυχικά τραύματα -ΔΙΑΦΥΛΆΞΤΕ ΓΕΝΙΚΆ ΤΗ ΖΩΉ ΣΑΣ ΑΠΌ ΒΑΘΕΙΆ ΨΥΧΙΚΆ ΤΡΑΎΜΑΤΑ -Pack my box with five dozen liquor jugs -Voix ambiguë d'un cœur qui au zéphyr préfère les jattes de kiwi -정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날 뚫훍뚫훍뚫(읗) 뚫훍뚫훍뚫(읗) 뚫훍뚫훍뚫 따다다 -Kæmi ný öxi hér, ykist þjófum nú bæði víl og ádrepa -Árvíztűrő tükörfúrógép Kŕdeľ ďatľov učí koňa žrať kôru -とりなくこゑす ゆめさませ みよあけわたる ひんかしを そらいろはえて おきつへに ほふねむれゐぬ もやのうち -鳥啼く声す 夢覚ませ 見よ明け渡る 東を 空色栄えて 沖つ辺に 帆船群れゐぬ 靄の中 -Înjurând pițigăiat, zoofobul comandă vexat whisky și tequila -Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства -Pijamalı hasta yağız şoföre çabucak güvendi -Also supports: ‛Unicode’ „quotation marks“—dashes…「括弧」‼ -ASCII Latin-1 Latin_Ext-A Latin_Ext-B Greek Cyrillic CJK-Ideo Kana Hangul_Syllables +x86(エックスはちろく)は、Intel 8086、およびその後方互換性を持つマイクロプロセッサの命令セットアーキテクチャの総称。 +16ビットの8086で登場し、32ビット拡張の80386(後にIA-32と命名)、64ビット拡張のx64、広義には更にAMDなどの互換プロセッサを含む。 + +x86 (англ. Intel 80x86) — архитектура процессора c одноимённым набором команд, впервые реализованная в процессорах +компании Intel. Название образовано от двух цифр, которыми заканчивались названия процессоров Intel ранних моделей — +8086, 80186, 80286 (i286), 80386 (i386), 80486 (i486). + +x86 on Intelin kehittämä ja valmistama suoritinarkkitehtuuri. Intel ei kuitenkaan ole arkkitehtuurin ainoa valmistaja +vaan myös AMD, Cyrix, NEC, Transmeta, VIA ja Zilog ovat valmistaneet x86-yhteensopivia suorittimia. + +เอกซ์86 (x86) เป็นชื่อทั่วไปของสถาปัตยกรรมคอมพิวเตอร์สำหรับไมโครโพรเซสเซอร์ที่สร้างโดยบริษัทอินเทล ปัจจุบันสถาปัตยกรรมแบบ x86 +เป็นสถาปัตยกรรมที่ได้รับความนิยมมากที่สุดในตลาดคอมพิวเตอร์เดสก์ท็อป, โน้ตบุ๊คและเซิร์ฟเวอร์ขนาดเล็ก นับตั้งแต่เริ่มใช้ในไอบีเอ็มพีซี ช่วงทศวรรษที่ 80 + +x86 (англ. Intel 80x86) — архітектура процесорів та ядра мікроконтролерів з однойменною системою команд. x86 або 80x86 +є загальною назвою мікропроцесорної архітектури та архітектури розробленої на її базі обчислювальної техніки. + +x86是一個指令集架構家族,最早由英特爾在1978年面市的「Intel 8086」CPU上開發出來。 +該系列較早期的處理器名稱是以數字來表示80x86。由於以“86”作為結尾,包括Intel 8086、80186、80286、80386以及80486,因此其架 +構被稱為“x86”。由於數字並不能作為註冊商標,因此Intel及其競爭者均在新一代處理器使用可註冊的名稱,如Pentium。 \ No newline at end of file diff --git a/terrarumsansbitmap/gdx/GameFontBase.kt b/terrarumsansbitmap/gdx/GameFontBase.kt index 58a4283..970d46c 100644 --- a/terrarumsansbitmap/gdx/GameFontBase.kt +++ b/terrarumsansbitmap/gdx/GameFontBase.kt @@ -189,9 +189,9 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo 0x3400..0x9FFF, 0x400..0x52F, 0xFF00..0xFF1F, - 0x2000..0x206F, + 0x2000..0x205F, 0x370..0x3CE, - 0xE00..0xE7F, + 0xE00..0xE5F, 0x530..0x58F, 0x10D0..0x10FF, 0x250..0x2AF, @@ -342,7 +342,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo textBGSize = widths - textBWidth = Array(str.length, { charIndex -> + textBWidth = IntArray(str.length, { charIndex -> if (charIndex == 0) 0 else { @@ -350,7 +350,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo (0..charIndex - 1).forEach { acc += maxOf(0, widths[it]) } // don't accumulate diacrtics (which has negative value) /*return*/acc } - }).toIntArray() + }) }