mirror of
https://github.com/curioustorvald/Terrarum-sans-bitmap.git
synced 2026-06-06 14:08:30 +09:00
WIP, at least it draws something
This commit is contained in:
Binary file not shown.
BIN
demo.PNG
BIN
demo.PNG
Binary file not shown.
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 14 KiB |
@@ -394,12 +394,12 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
0x2C60..0x2C7F
|
0x2C60..0x2C7F
|
||||||
)
|
)
|
||||||
private val glyphProps: HashMap<Int, GlyphProps> = HashMap()
|
private val glyphProps: HashMap<Int, GlyphProps> = HashMap()
|
||||||
private val sheets: Array<TextureRegionPack>
|
private val sheets: Array<PixmapRegionPack>
|
||||||
|
|
||||||
private var charsetOverride = 0
|
private var charsetOverride = 0
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val sheetsPack = ArrayList<TextureRegionPack>()
|
val sheetsPack = ArrayList<PixmapRegionPack>()
|
||||||
|
|
||||||
// first we create pixmap to read pixels, then make texture using pixmap
|
// first we create pixmap to read pixels, then make texture using pixmap
|
||||||
fileList.forEachIndexed { index, it ->
|
fileList.forEachIndexed { index, it ->
|
||||||
@@ -470,44 +470,46 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
buildWidthTableFixed()
|
buildWidthTableFixed()
|
||||||
|
|
||||||
|
|
||||||
if (!noShadow) {
|
/*if (!noShadow) {
|
||||||
makeShadow(pixmap)
|
makeShadowForSheet(pixmap)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
val texture = Texture(pixmap)
|
//val texture = Texture(pixmap)
|
||||||
val texRegPack = if (isVariable) {
|
val texRegPack = if (isVariable) {
|
||||||
TextureRegionPack(texture, W_VAR_INIT, H, HGAP_VAR, 0, xySwapped = isXYSwapped)
|
PixmapRegionPack(pixmap, W_VAR_INIT, H, HGAP_VAR, 0, xySwapped = isXYSwapped)
|
||||||
}
|
}
|
||||||
else if (index == SHEET_UNIHAN) {
|
else if (index == SHEET_UNIHAN) {
|
||||||
TextureRegionPack(texture, W_UNIHAN, H_UNIHAN) // the only exception that is height is 16
|
PixmapRegionPack(pixmap, W_UNIHAN, H_UNIHAN) // the only exception that is height is 16
|
||||||
}
|
}
|
||||||
// below they all have height of 20 'H'
|
// below they all have height of 20 'H'
|
||||||
else if (index == SHEET_FW_UNI) {
|
else if (index == SHEET_FW_UNI) {
|
||||||
TextureRegionPack(texture, W_UNIHAN, H)
|
PixmapRegionPack(pixmap, W_UNIHAN, H)
|
||||||
}
|
}
|
||||||
else if (index == SHEET_CJK_PUNCT) {
|
else if (index == SHEET_CJK_PUNCT) {
|
||||||
TextureRegionPack(texture, W_ASIAN_PUNCT, H)
|
PixmapRegionPack(pixmap, W_ASIAN_PUNCT, H)
|
||||||
}
|
}
|
||||||
else if (index == SHEET_KANA) {
|
else if (index == SHEET_KANA) {
|
||||||
TextureRegionPack(texture, W_KANA, H)
|
PixmapRegionPack(pixmap, W_KANA, H)
|
||||||
}
|
}
|
||||||
else if (index == SHEET_HANGUL) {
|
else if (index == SHEET_HANGUL) {
|
||||||
TextureRegionPack(texture, W_HANGUL, H)
|
PixmapRegionPack(pixmap, W_HANGUL, H)
|
||||||
}
|
}
|
||||||
else if (index == SHEET_CUSTOM_SYM) {
|
else if (index == SHEET_CUSTOM_SYM) {
|
||||||
TextureRegionPack(texture, SIZE_CUSTOM_SYM, SIZE_CUSTOM_SYM) // TODO variable
|
PixmapRegionPack(pixmap, SIZE_CUSTOM_SYM, SIZE_CUSTOM_SYM) // TODO variable
|
||||||
}
|
}
|
||||||
else if (index == SHEET_RUNIC) {
|
else if (index == SHEET_RUNIC) {
|
||||||
TextureRegionPack(texture, W_LATIN_WIDE, H)
|
PixmapRegionPack(pixmap, W_LATIN_WIDE, H)
|
||||||
}
|
}
|
||||||
else throw IllegalArgumentException("[TerrarumSansBitmap] Unknown sheet index: $index")
|
else throw IllegalArgumentException("[TerrarumSansBitmap] Unknown sheet index: $index")
|
||||||
|
|
||||||
texRegPack.texture.setFilter(minFilter, magFilter)
|
//texRegPack.texture.setFilter(minFilter, magFilter)
|
||||||
|
|
||||||
sheetsPack.add(texRegPack)
|
sheetsPack.add(texRegPack)
|
||||||
|
|
||||||
pixmap.dispose() // you are terminated
|
|
||||||
|
|
||||||
|
//pixmap.dispose() // you are terminated
|
||||||
}
|
}
|
||||||
|
|
||||||
sheets = sheetsPack.toTypedArray()
|
sheets = sheetsPack.toTypedArray()
|
||||||
@@ -545,6 +547,10 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
|
|
||||||
private var nullProp = GlyphProps(15, 0)
|
private var nullProp = GlyphProps(15, 0)
|
||||||
|
|
||||||
|
private var pixmapTextureHolder: Texture? = null
|
||||||
|
private var pixmapHolder: Pixmap? = null
|
||||||
|
|
||||||
|
private val pixmapOffsetY = -10
|
||||||
|
|
||||||
override fun draw(batch: Batch, charSeq: CharSequence, x: Float, y: Float): GlyphLayout? {
|
override fun draw(batch: Batch, charSeq: CharSequence, x: Float, y: Float): GlyphLayout? {
|
||||||
val oldProjectionMatrix = batch.projectionMatrix
|
val oldProjectionMatrix = batch.projectionMatrix
|
||||||
@@ -553,13 +559,12 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
|
|
||||||
|
|
||||||
// always draw at integer position; this is bitmap font after all
|
// always draw at integer position; this is bitmap font after all
|
||||||
val x = Math.round(x).toFloat()
|
val x = Math.round(x).toInt()//.toFloat()
|
||||||
val y = Math.round(y).toFloat()
|
val y = Math.round(y).toInt()//.toFloat()
|
||||||
|
|
||||||
|
|
||||||
if (charSeq.isNotBlank()) {
|
if (charSeq.isNotBlank()) {
|
||||||
|
|
||||||
|
|
||||||
if (!textCache.containsKey(charSeq) || firstRun) {
|
if (!textCache.containsKey(charSeq) || firstRun) {
|
||||||
textBuffer = charSeq.toCodePoints()
|
textBuffer = charSeq.toCodePoints()
|
||||||
|
|
||||||
@@ -612,7 +617,13 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
//println()
|
//println()
|
||||||
|
|
||||||
|
|
||||||
resetHash(charSeq, x, y)
|
resetHash(charSeq, x.toFloat(), y.toFloat())
|
||||||
|
|
||||||
|
pixmapHolder?.dispose() /* you can do this one */
|
||||||
|
//pixmapTextureHolder?.dispose() /* you CAN'T do this however */
|
||||||
|
|
||||||
|
pixmapHolder = Pixmap(getWidth(textBuffer), H + -(pixmapOffsetY * 2), Pixmap.Format.RGBA8888)
|
||||||
|
|
||||||
var index = 0
|
var index = 0
|
||||||
while (index <= textBuffer.lastIndex) {
|
while (index <= textBuffer.lastIndex) {
|
||||||
val c = textBuffer[index]
|
val c = textBuffer[index]
|
||||||
@@ -654,10 +665,18 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
batch.color = mainCol
|
//batch.color = mainCol
|
||||||
batch.draw(hangulSheet.get(indexCho, choRow), x + posXbuffer[index].toFloat(), y)
|
val choTex = hangulSheet.get(indexCho, choRow)
|
||||||
batch.draw(hangulSheet.get(indexJung, jungRow), x + posXbuffer[index].toFloat(), y)
|
val jungTex = hangulSheet.get(indexJung, jungRow)
|
||||||
batch.draw(hangulSheet.get(indexJong, jongRow), x + posXbuffer[index].toFloat(), y)
|
val jongTex = hangulSheet.get(indexJong, jongRow)
|
||||||
|
|
||||||
|
pixmapHolder?.drawPixmap(choTex, posXbuffer[index], pixmapOffsetY)
|
||||||
|
pixmapHolder?.drawPixmap(jungTex, posXbuffer[index], pixmapOffsetY)
|
||||||
|
pixmapHolder?.drawPixmap(jongTex, posXbuffer[index], pixmapOffsetY)
|
||||||
|
|
||||||
|
//batch.draw(choTex, x + posXbuffer[index].toFloat(), y)
|
||||||
|
//batch.draw(jungTex, x + posXbuffer[index].toFloat(), y)
|
||||||
|
//batch.draw(hangulSheet.get(indexJong, jongRow), x + posXbuffer[index].toFloat(), y)
|
||||||
|
|
||||||
|
|
||||||
index += hangulLength - 1
|
index += hangulLength - 1
|
||||||
@@ -665,22 +684,24 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
val posY = y + posYbuffer[index].flipY() +
|
val posY = posYbuffer[index].flipY() +
|
||||||
if (sheetID == SHEET_UNIHAN) // evil exceptions
|
if (sheetID == SHEET_UNIHAN) // evil exceptions
|
||||||
offsetUnihan
|
offsetUnihan
|
||||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
else if (sheetID == SHEET_CUSTOM_SYM)
|
||||||
offsetCustomSym
|
offsetCustomSym
|
||||||
else 0
|
else 0
|
||||||
|
|
||||||
val posX = x + posXbuffer[index]
|
val posX = posXbuffer[index]
|
||||||
val texture = sheets[sheetID].get(sheetX, sheetY)
|
val texture = sheets[sheetID].get(sheetX, sheetY)
|
||||||
|
|
||||||
batch.color = mainCol
|
//batch.color = mainCol
|
||||||
batch.draw(texture, posX, posY)
|
pixmapHolder?.drawPixmap(texture, posX, posY + pixmapOffsetY)
|
||||||
|
|
||||||
|
//batch.draw(texture, posX, posY)
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (noSuchGlyph: ArrayIndexOutOfBoundsException) {
|
catch (noSuchGlyph: ArrayIndexOutOfBoundsException) {
|
||||||
batch.color = mainCol
|
//batch.color = mainCol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,6 +709,11 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batch.color = mainCol
|
||||||
|
makeShadow(pixmapHolder)
|
||||||
|
pixmapTextureHolder = Texture(pixmapHolder)
|
||||||
|
batch.draw(pixmapTextureHolder, x.toFloat(), y.toFloat())
|
||||||
|
|
||||||
/*textTexture.end()
|
/*textTexture.end()
|
||||||
|
|
||||||
|
|
||||||
@@ -713,6 +739,11 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
sheets.forEach { it.dispose() }
|
sheets.forEach { it.dispose() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for positioning letters, NOT for the actual width.
|
||||||
|
*
|
||||||
|
* For actual width, use `getWidth()`
|
||||||
|
*/
|
||||||
private fun getWidthOfCharSeq(s: CodepointSequence): IntArray {
|
private fun getWidthOfCharSeq(s: CodepointSequence): IntArray {
|
||||||
val len = IntArray(s.size)
|
val len = IntArray(s.size)
|
||||||
for (i in 0..s.lastIndex) {
|
for (i in 0..s.lastIndex) {
|
||||||
@@ -1007,8 +1038,9 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
|
|
||||||
private val glyphLayout = GlyphLayout()
|
private val glyphLayout = GlyphLayout()
|
||||||
|
|
||||||
fun getWidth(text: String): Int {
|
fun getWidth(text: String) = getWidth(text.toCodePoints())
|
||||||
var s = text.toCodePoints()
|
|
||||||
|
fun getWidth(s: CodepointSequence): Int {
|
||||||
var len = 0
|
var len = 0
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
@@ -1296,9 +1328,7 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
*
|
*
|
||||||
* The pixmap must be mutable (beware of concurrentmodificationexception).
|
* The pixmap must be mutable (beware of concurrentmodificationexception).
|
||||||
*/
|
*/
|
||||||
private fun makeShadow(pixmap: Pixmap) {
|
private fun makeShadowForSheet(pixmap: Pixmap) {
|
||||||
|
|
||||||
|
|
||||||
for (y in 0..pixmap.height - 2) {
|
for (y in 0..pixmap.height - 2) {
|
||||||
for (x in 0..pixmap.width - 2) {
|
for (x in 0..pixmap.width - 2) {
|
||||||
val pxNow = pixmap.getPixel(x, y) // RGBA8888
|
val pxNow = pixmap.getPixel(x, y) // RGBA8888
|
||||||
@@ -1329,6 +1359,40 @@ class GameFontBase(fontDir: String, val noShadow: Boolean = false, val flipY: Bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits the given pixmap so that it would have a shadow on it.
|
||||||
|
*
|
||||||
|
* Meant to be used to give shadow to a linotype (typeset-finished line of pixmap)
|
||||||
|
*
|
||||||
|
* The pixmap must be mutable (beware of concurrentmodificationexception).
|
||||||
|
*/
|
||||||
|
private fun makeShadow(pixmap: Pixmap?) {
|
||||||
|
if (pixmap == null) return
|
||||||
|
|
||||||
|
for (y in 0..pixmap.height - 2) {
|
||||||
|
for (x in 0..pixmap.width - 2) {
|
||||||
|
val pxNow = pixmap.getPixel(x, y) // RGBA8888
|
||||||
|
|
||||||
|
if (pxNow and 0xFF == 255) {
|
||||||
|
val pxRight = (x + 1) to y
|
||||||
|
val pxBottom = x to (y + 1)
|
||||||
|
val pxBottomRight = (x + 1) to (y + 1)
|
||||||
|
val opCue = listOf(pxRight, pxBottom, pxBottomRight)
|
||||||
|
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** High surrogate comes before the low. */
|
/** High surrogate comes before the low. */
|
||||||
private fun Char.isHighSurrogate() = (this.toInt() in 0xD800..0xDBFF)
|
private fun Char.isHighSurrogate() = (this.toInt() in 0xD800..0xDBFF)
|
||||||
/** CodePoint = 0x10000 + (H - 0xD800) * 0x400 + (L - 0xDC00) */
|
/** CodePoint = 0x10000 + (H - 0xD800) * 0x400 + (L - 0xDC00) */
|
||||||
|
|||||||
73
src/net/torvald/terrarumsansbitmap/gdx/PixmapRegionPack.kt
Normal file
73
src/net/torvald/terrarumsansbitmap/gdx/PixmapRegionPack.kt
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package net.torvald.terrarumsansbitmap.gdx
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2018-09-17.
|
||||||
|
*/
|
||||||
|
class PixmapRegionPack(
|
||||||
|
pixmap: Pixmap,
|
||||||
|
val tileW: Int,
|
||||||
|
val tileH: Int,
|
||||||
|
val hGap: Int = 0,
|
||||||
|
val vGap: Int = 0,
|
||||||
|
val hFrame: Int = 0,
|
||||||
|
val vFrame: Int = 0,
|
||||||
|
val xySwapped: Boolean = false // because Unicode chart does, duh
|
||||||
|
) {
|
||||||
|
|
||||||
|
//constructor(ref: String, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false) :
|
||||||
|
// this(Pixmap(ref), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped)
|
||||||
|
constructor(fileHandle: FileHandle, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false) :
|
||||||
|
this(Pixmap(fileHandle), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped)
|
||||||
|
|
||||||
|
val horizontalCount = (pixmap.width - 2 * hFrame + hGap) / (tileW + hGap)
|
||||||
|
val verticalCount = (pixmap.height - 2 * vFrame + vGap) / (tileH + vGap)
|
||||||
|
|
||||||
|
val regions: Array<Pixmap>
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (!xySwapped) {
|
||||||
|
regions = Array<Pixmap>(horizontalCount * verticalCount, {
|
||||||
|
val region = Pixmap(tileW, tileH, Pixmap.Format.RGBA8888)
|
||||||
|
val rx = (it % horizontalCount * (tileW + hGap)) + hFrame
|
||||||
|
val ry = (it / horizontalCount * (tileH + vGap)) + vFrame
|
||||||
|
|
||||||
|
region.drawPixmap(pixmap, 0, 0,
|
||||||
|
rx * (tileW + hGap),
|
||||||
|
ry * (tileH + vGap),
|
||||||
|
tileW, tileH
|
||||||
|
)
|
||||||
|
|
||||||
|
// todo globalFlipY ?
|
||||||
|
|
||||||
|
/*return*/region
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
regions = Array<Pixmap>(horizontalCount * verticalCount, {
|
||||||
|
val region = Pixmap(tileW, tileH, Pixmap.Format.RGBA8888)
|
||||||
|
val rx = (it / verticalCount * (tileW + hGap)) + hFrame
|
||||||
|
val ry = (it % verticalCount * (tileH + vGap)) + vFrame
|
||||||
|
|
||||||
|
region.drawPixmap(pixmap, 0, 0,
|
||||||
|
rx * (tileW + hGap),
|
||||||
|
ry * (tileH + vGap),
|
||||||
|
tileW, tileH
|
||||||
|
)
|
||||||
|
|
||||||
|
// todo globalFlipY ?
|
||||||
|
|
||||||
|
/*return*/region
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(x: Int, y: Int) = regions[y * horizontalCount + x]
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
regions.forEach { it.dispose() }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user