fixed getWidth() not returning correct width

getWidth() is heavier than ever now, at least it's cached
This commit is contained in:
Minjae Song
2019-01-10 20:11:36 +09:00
parent d88443814f
commit b62fee89cb
2 changed files with 43 additions and 67 deletions

View File

@@ -33,10 +33,10 @@ import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.terrarumsansbitmap.GlyphProps import net.torvald.terrarumsansbitmap.GlyphProps
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.FileOutputStream import java.io.FileOutputStream
import java.lang.NullPointerException
import java.security.MessageDigest import java.security.MessageDigest
import java.util.zip.CRC32 import java.util.zip.CRC32
import java.util.zip.GZIPInputStream import java.util.zip.GZIPInputStream
import kotlin.NullPointerException
import kotlin.math.roundToInt import kotlin.math.roundToInt
typealias CodepointSequence = ArrayList<CodePoint> typealias CodepointSequence = ArrayList<CodePoint>
@@ -288,7 +288,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
// TODO (val posXbuffer: IntArray, val posYbuffer: IntArray) -> (val linotype: Pixmap) // TODO (val posXbuffer: IntArray, val posYbuffer: IntArray) -> (val linotype: Pixmap)
private data class ShittyGlyphLayout(val textBuffer: CodepointSequence, val linotype: Pixmap) private data class ShittyGlyphLayout(val textBuffer: CodepointSequence, val linotype: Pixmap, val width: Int)
//private val textCache = HashMap<CharSequence, ShittyGlyphLayout>() //private val textCache = HashMap<CharSequence, ShittyGlyphLayout>()
@@ -300,7 +300,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
/** /**
* Insertion sorts the last element fo the textCache * Insertion sorts the last element fo the textCache
*/ */
private fun addToCache(text: CodepointSequence, linotype: Pixmap) { private fun addToCache(text: CodepointSequence, linotype: Pixmap, width: Int) {
// make room first // make room first
if (textCacheCap == textCacheSize - 1) { if (textCacheCap == textCacheSize - 1) {
var c = 0 var c = 0
@@ -323,7 +323,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
// put new element at the end // put new element at the end
textCache[textCacheCap] = TextCacheObj(textCacheCap, text.getHash(), ShittyGlyphLayout(text, linotype)) textCache[textCacheCap] = TextCacheObj(textCacheCap, text.getHash(), ShittyGlyphLayout(text, linotype, width))
@@ -698,7 +698,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
if (!cacheContains(charSeqHash) || flagFirstRun) { if (!cacheContains(charSeqHash) || flagFirstRun) {
textBuffer = charSeq.toCodePoints() textBuffer = charSeq.toCodePoints()
val (posXbuffer, posYbuffer) = buildWidthAndPosBuffers() val (posXbuffer, posYbuffer) = buildWidthAndPosBuffers(textBuffer)
linotype = null // use new linotype linotype = null // use new linotype
flagFirstRun = false flagFirstRun = false
@@ -714,7 +714,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
//pixmapTextureHolder?.dispose() /* you CAN'T do this however */ //pixmapTextureHolder?.dispose() /* you CAN'T do this however */
linotype = Pixmap(getWidth(textBuffer), H + (pixmapOffsetY * 2), Pixmap.Format.RGBA8888) linotype = Pixmap(posXbuffer.last(), H + (pixmapOffsetY * 2), Pixmap.Format.RGBA8888)
// TEST: does the new instance of pixmap is all zero? // TEST: does the new instance of pixmap is all zero?
/*repeat(pixmapHolder?.pixels?.capacity() ?: 0) { /*repeat(pixmapHolder?.pixels?.capacity() ?: 0) {
@@ -818,7 +818,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
// put things into cache // put things into cache
//textCache[charSeq] = ShittyGlyphLayout(textBuffer, linotype!!) //textCache[charSeq] = ShittyGlyphLayout(textBuffer, linotype!!)
addToCache(textBuffer, linotype!!) addToCache(textBuffer, linotype!!, posXbuffer.last())
} }
else { else {
val bufferObj = getCache(charSeqHash) val bufferObj = getCache(charSeqHash)
@@ -1161,69 +1161,21 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
fun getWidth(text: String) = getWidth(text.toCodePoints()) fun getWidth(text: String) = getWidth(text.toCodePoints())
fun getWidth(s: CodepointSequence): Int { fun getWidth(s: CodepointSequence): Int {
var len = 0 try {
val cacheObj = getCache(s.getHash())
var i = 0 return cacheObj.glyphLayout!!.width
while (i <= s.lastIndex) { }
val chr = s[i] catch (e: NullPointerException) {
val ctype = getSheetType(s[i]) return buildWidthAndPosBuffers(s).first.last()
var len2 = 0
if (variableWidthSheets.contains(ctype)) {
if (!glyphProps.containsKey(chr)) {
System.err.println("[TerrarumSansBitmap] no width data for glyph number ${Integer.toHexString(chr.toInt()).toUpperCase()}")
len2 = W_LATIN_WIDE
}
val prop = glyphProps[chr] ?: nullProp
if (!prop.writeOnTop)
len2 = prop.width
}
else if (isColourCode(chr) || isCharsetOverride(chr))
len2 = 0
else if (ctype == SHEET_CJK_PUNCT)
len2 = W_ASIAN_PUNCT
else if (ctype == SHEET_HANGUL) {
// hangul IPF canonical and special cases
val cNext = if (i + 1 < s.size) s[i + 1] else 0
val cNextNext = if (i + 2 < s.size) s[i + 2] else 0
val hangulLength = if (isHangulJongseong(cNextNext) && isHangulJungseong(cNext))
3
else if (isHangulJungseong(cNext))
2
else
1
len2 = W_HANGUL
i += hangulLength - 1
}
else if (ctype == SHEET_KANA)
len2 = W_KANA
else if (unihanWidthSheets.contains(ctype))
len2 = W_UNIHAN
else if (ctype == SHEET_CUSTOM_SYM)
len2 = SIZE_CUSTOM_SYM
else
len2 = W_LATIN_WIDE
len += len2 * scale
if (i < s.lastIndex) len += interchar
i++
} }
return len
} }
private fun buildWidthAndPosBuffers(): Pair<IntArray, IntArray> { /**
val str = textBuffer * posXbuffer's size is greater than the string, last element marks the width of entire string.
val widths = getWidthOfCharSeq(str) */
private fun buildWidthAndPosBuffers(str: CodepointSequence): Pair<IntArray, IntArray> {
val posXbuffer = IntArray(str.size, { 0 }) val posXbuffer = IntArray(str.size + 1, { 0 })
val posYbuffer = IntArray(str.size, { 0 }) val posYbuffer = IntArray(str.size, { 0 })
@@ -1233,7 +1185,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
val HALF_VAR_INIT = W_VAR_INIT.minus(1).div(2) val HALF_VAR_INIT = W_VAR_INIT.minus(1).div(2)
for (charIndex in 0 until posXbuffer.size) { for (charIndex in 0 until posXbuffer.size - 1) {
if (charIndex > 0) { if (charIndex > 0) {
// nonDiacriticCounter allows multiple diacritics // nonDiacriticCounter allows multiple diacritics
@@ -1349,6 +1301,30 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
} }
} }
// fill the last of the posXbuffer
if (str.isNotEmpty()) {
val lastCharProp = glyphProps[str.last()]
val penultCharProp = glyphProps[nonDiacriticCounter]!!
posXbuffer[posXbuffer.lastIndex] = 1 + posXbuffer[posXbuffer.lastIndex - 1] + // adding 1 to house the shadow
if (lastCharProp?.writeOnTop == true) {
val realDiacriticWidth = if (lastCharProp.alignWhere == GlyphProps.ALIGN_CENTRE) {
(lastCharProp.width).div(2) + penultCharProp.alignXPos
}
else if (lastCharProp.alignWhere == GlyphProps.ALIGN_RIGHT) {
(lastCharProp.width) + penultCharProp.alignXPos
}
else 0
maxOf(penultCharProp.width, realDiacriticWidth)
}
else {
(lastCharProp?.width ?: 0)
}
}
else {
posXbuffer[0] = 0
}
return posXbuffer to posYbuffer return posXbuffer to posYbuffer
} }