First working version of the Keming Machine
@@ -38,19 +38,29 @@ Width is encoded in binary bits, on pixels. On the font spritesheet, every glyph
|
|||||||
|
|
||||||
### Glyph Tags
|
### Glyph Tags
|
||||||
|
|
||||||
Green-tinted area (should be 10 px tall) contains the tags. Tags are defined as following:
|
Rightmost vertical column (should be 20 px tall) contains the tags. Tags are defined as following:
|
||||||
|
|
||||||
```
|
```
|
||||||
(LSB) 0 == Use Compiler Directive (Undefined right now, keep it as 0)
|
(LSB) W -,
|
||||||
1 -, 1 = Align to this X pos of prev char,
|
W |
|
||||||
1 | 2 = only valid if write-on-top is 1
|
W |= Width of the character
|
||||||
1 | 4 = and is centre-aligned and non-zero
|
W |
|
||||||
1 -' 8 = (if this is zero, floorOf(width/2) will be used instead)
|
W -'
|
||||||
0 -, 0 Align 1 Align 0 Align 1 Align before
|
m --Is this character lowheight?
|
||||||
1 -' 0 left 0 right 1 centre 1 the glyph
|
K -,
|
||||||
1 == write-on-top, usually it's diatritics but not always (e.g. devanagari vowel sign O)
|
K |= Tags used by the "Keming Machine"
|
||||||
1 -, 0 Stack 1 Stack 0 Before 1 Up &
|
K |
|
||||||
(MSB) 0 -' 0 up 0 down 1 &After 1 Down (e.g. U+0C48)
|
K -' ,-Unused
|
||||||
|
· --'
|
||||||
|
X -, Align to this X pos of prev char, only valid if write-on-top is 1
|
||||||
|
X |= and is centre-aligned and non-zero
|
||||||
|
X | (if this is zero, floorOf(width/2) will be used instead)
|
||||||
|
X -'
|
||||||
|
A -,_ 0 Align 1 Align 0 Align 1 Align before
|
||||||
|
A -' 0 left 0 right 1 centre 1 the glyph
|
||||||
|
D --write-on-top, usually it's diatritics but not always (e.g. devanagari vowel sign O)
|
||||||
|
S -,_ 0 Stack 1 Stack 0 Before 1 Up &
|
||||||
|
(MSB) S -' 0 up 0 down 1 &After 1 Down (e.g. U+0C48)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Stack Up/Down
|
#### Stack Up/Down
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 280 KiB |
BIN
demo.PNG
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 142 KiB |
@@ -5,7 +5,8 @@ There are many bitmap fonts on the internet. You care for the multilingual suppo
|
|||||||
most of them do not support your language, vector fonts take too much time to load, and even
|
most of them do not support your language, vector fonts take too much time to load, and even
|
||||||
then their legibility suffers because screw built-in antialias.
|
then their legibility suffers because screw built-in antialias.
|
||||||
|
|
||||||
You somehow found a multilingual one, and it makes your game look like an old computer, and you say:
|
You somehow found a multilingual one, and it makes your text as if they came straight from an old
|
||||||
|
computer terminal, and you say:
|
||||||
|
|
||||||
“Well, better than nothing… no, it’s ugly.”
|
“Well, better than nothing… no, it’s ugly.”
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 1.1 KiB |
115
keming_machine.txt
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
--- Pixel 0
|
||||||
|
- Lowheight bit
|
||||||
|
- encoding: has pixel - it's low height
|
||||||
|
- used by the diacritics system to quickly look up if the character is low height without parsing the Pixel 1
|
||||||
|
|
||||||
|
### Legends
|
||||||
|
#
|
||||||
|
# ͞ A·B < unset for lowheight miniscules, as in e
|
||||||
|
# |·| < space we don't care
|
||||||
|
#――C·D < middle hole for majuscules, as in C
|
||||||
|
# E·F < middle hole for miniscules, as in c
|
||||||
|
# ͟ G·H
|
||||||
|
# ――― < baseline
|
||||||
|
# |·|
|
||||||
|
# J·K
|
||||||
|
|
||||||
|
--- Pixel 1
|
||||||
|
- A..K Occupied (1024)
|
||||||
|
- Is ABGH are all Ys instead of Bars? (2)
|
||||||
|
- Say, A is Bar but E is wye (e.g. Ꮨ), this condition is false; this character must be encoded as ABDFGH(B).
|
||||||
|
- encoding:
|
||||||
|
- <MSB> Y0000000 JK000000 ABCDEFGH <LSB>
|
||||||
|
- Y: Bar/Wye Mode
|
||||||
|
- A..K: arguments
|
||||||
|
- B-type will contract the space by 2 pixels, while Y-type will do it by 1
|
||||||
|
|
||||||
|
# Capital/lower itself is given using the pixel 0 due to the diacritics processing
|
||||||
|
|
||||||
|
--- Examples
|
||||||
|
- AB(B): T
|
||||||
|
- ABCEGH(B): C
|
||||||
|
- ABCEFGH(Y): K
|
||||||
|
- ABCDEG: Ꮅ
|
||||||
|
- ABCDEFGH: B,D,O
|
||||||
|
- ABCDFH: Ч
|
||||||
|
- ABCEG: Г
|
||||||
|
- ABGH: Ꮖ
|
||||||
|
- ACDEG: Ꮀ
|
||||||
|
- ACDEFGH: h,Ƅ
|
||||||
|
- ACDFH: ߆
|
||||||
|
- ACEGH: L
|
||||||
|
- AH(Y): \
|
||||||
|
- BDEFGH: J
|
||||||
|
- BDFGH: ɺ,ป
|
||||||
|
- BG(Y): /
|
||||||
|
- CD: Ⴕ
|
||||||
|
- CDEF(Y): Φ
|
||||||
|
- CDEFGH: a,c,e,i,o,φ,ϕ
|
||||||
|
- CDEFGHJK: g
|
||||||
|
- CDEFGHK: ƞ
|
||||||
|
|
||||||
|
- AB(Y): Y
|
||||||
|
- ABCD(Y): V
|
||||||
|
- CDEF(Y): v
|
||||||
|
- EFGH(Y): ʌ
|
||||||
|
- CDGH(Y): A
|
||||||
|
|
||||||
|
--- Rules
|
||||||
|
# Legend: _ dont care
|
||||||
|
# @ must have a bit set
|
||||||
|
# ` must have a bit unset
|
||||||
|
- ͟A͟B͟C͟D͟E͟F͟G͟H͟J͟K͟ ͟ ͟ ͟A͟B͟C͟D͟E͟F͟G͟H͟J͟K͟
|
||||||
|
- _@_`___`__ — `_________ # Γe,TJ ; Ye,YJ,Ve,VJ,TA,ΓA,VA,Vʌ,YA,Yʌ,yA,yʌ,/a,/d
|
||||||
|
- _@_@___`__ — `___`_@___ # Pɺ but NOT PJ
|
||||||
|
- ___`_`____ — `___@_`___ # Cꟶ,Kꟶ,Lꟶ,Γꟶ
|
||||||
|
- ___`_`____ — `_@___`___ # CꟵ,KꟵ,LꟵ,ΓꟵ
|
||||||
|
-----------------------------------------------------
|
||||||
|
- _`________ — @_`___`___ # eꞀ,LT ; eY,LY,eV,LV,AT,AꞀ,AY,Ay,λY,λy,a\,b\
|
||||||
|
- _`___`_@__ — @_@___`___ # Lꟼ but NOT bꟼ
|
||||||
|
- _`___@_`__ — __`_`_____ # ⱶƆ,ⱶJ
|
||||||
|
- _`_@___`__ — __`_`_____ # ⱵƆ,ⱵJ
|
||||||
|
|
||||||
|
|
||||||
|
--- Implementation
|
||||||
|
code: |
|
||||||
|
val posTable = intArrayOf(7,6,5,4,3,2,1,0,9,8)
|
||||||
|
|
||||||
|
class RuleMask(s: String) {
|
||||||
|
|
||||||
|
private var careBits = 0
|
||||||
|
private var ruleBits = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
s.forEachIndexed { index, char ->
|
||||||
|
when (char) {
|
||||||
|
'@' -> {
|
||||||
|
careBits = careBits or (1 shl posTable[index])
|
||||||
|
ruleBits = ruleBits or (1 shl posTable[index])
|
||||||
|
}
|
||||||
|
'`' -> {
|
||||||
|
careBits = careBits or (1 shl posTable[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun matches(shapeBits: Int) = ((shapeBits and careBits) and ruleBits) == 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Pixel 2
|
||||||
|
Glyph pos for up/down diacritics
|
||||||
|
- U: X-position for stack-up diacritics
|
||||||
|
- D: X-position for stack-down diacritics
|
||||||
|
- encoding:
|
||||||
|
- <MSB> 00000000 100DDDDD 100UUUUU <LSB>
|
||||||
|
- If either U/D is unused, centre position will be used.
|
||||||
|
- Diacritics will be centred on the x-position this parameter points to
|
||||||
|
|
||||||
|
--- Pixel 3
|
||||||
|
dot removal for diacritics:
|
||||||
|
- All 24 bits are used to put replacement character
|
||||||
|
- encoding:
|
||||||
|
- <MSB> RRRRRRRR GGGGGGGG BBBBBBBB <LSB>
|
||||||
|
|
||||||
@@ -10,7 +10,12 @@ data class GlyphProps(
|
|||||||
val alignXPos: Int,
|
val alignXPos: Int,
|
||||||
val rtl: Boolean = false,
|
val rtl: Boolean = false,
|
||||||
val stackWhere: Int = 0,
|
val stackWhere: Int = 0,
|
||||||
var extInfo: IntArray? = null
|
var extInfo: IntArray? = null,
|
||||||
|
|
||||||
|
val hasKernData: Boolean = false,
|
||||||
|
val isLowheight: Boolean = false,
|
||||||
|
val isKernYtype: Boolean = false,
|
||||||
|
val kerningMask: Int = 255
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val ALIGN_LEFT = 0
|
const val ALIGN_LEFT = 0
|
||||||
@@ -38,6 +43,21 @@ data class GlyphProps(
|
|||||||
tags.ushr(8).and(3)
|
tags.ushr(8).and(3)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
constructor(width: Int, tags: Int, isLowheight: Boolean, isKernYtype: Boolean, kerningMask: Int) : this(
|
||||||
|
width,
|
||||||
|
tags.ushr(7).and(1) == 1,
|
||||||
|
tags.ushr(5).and(3),
|
||||||
|
tags.ushr(1).and(15),
|
||||||
|
tags.and(1) == 1,
|
||||||
|
tags.ushr(8).and(3),
|
||||||
|
null,
|
||||||
|
|
||||||
|
true,
|
||||||
|
isLowheight,
|
||||||
|
isKernYtype,
|
||||||
|
kerningMask
|
||||||
|
)
|
||||||
|
|
||||||
fun isOverlay() = writeOnTop && alignXPos == 1
|
fun isOverlay() = writeOnTop && alignXPos == 1
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
|
|||||||
@@ -726,13 +726,28 @@ class TerrarumSansBitmap(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// lowheight bit
|
||||||
|
val isLowHeight = (pixmap.getPixel(codeStartX, codeStartY + 5).and(0xFF) != 0)
|
||||||
|
|
||||||
|
// Keming machine parameters
|
||||||
|
val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6)
|
||||||
|
val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7)
|
||||||
|
val kerningBit3 = pixmap.getPixel(codeStartX, codeStartY + 8)
|
||||||
|
val isKerningYtype = ((kerningBit1 and 0x80000000.toInt()) != 0)
|
||||||
|
val kerningMask = kerningBit1.ushr(8).and(0xFFFFFF)
|
||||||
|
val hasKerningBit = kerningBit1 and 255 != 0//(kerningBit1 and 255 != 0 && kerningMask != 0xFFFF)
|
||||||
|
|
||||||
|
|
||||||
//println("$code: Width $width, tags $tags")
|
//println("$code: Width $width, tags $tags")
|
||||||
|
if (hasKerningBit)
|
||||||
|
println("$code: W $width, tags $tags, low? $isLowHeight, kern ${kerningMask.toString(16).padStart(6,'0')} (raw: ${kerningBit1.toLong().and(4294967295).toString(16).padStart(8,'0')})")
|
||||||
|
|
||||||
/*val isDiacritics = pixmap.getPixel(codeStartX, codeStartY + H - 1).and(0xFF) != 0
|
/*val isDiacritics = pixmap.getPixel(codeStartX, codeStartY + H - 1).and(0xFF) != 0
|
||||||
if (isDiacritics)
|
if (isDiacritics)
|
||||||
glyphWidth = -glyphWidth*/
|
glyphWidth = -glyphWidth*/
|
||||||
|
|
||||||
glyphProps[code] = GlyphProps(width, tags)
|
glyphProps[code] = if (hasKerningBit) GlyphProps(width, tags, isLowHeight, isKerningYtype, kerningMask) else GlyphProps(width, tags)
|
||||||
|
|
||||||
// extra info
|
// extra info
|
||||||
val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0
|
val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0
|
||||||
@@ -752,6 +767,7 @@ class TerrarumSansBitmap(
|
|||||||
glyphProps[code]!!.extInfo!![x] = info
|
glyphProps[code]!!.extInfo!![x] = info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1337,6 +1353,90 @@ class TerrarumSansBitmap(
|
|||||||
return crc.value.toInt()
|
return crc.value.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CodePoint.isLowHeight() = glyphProps[this]?.isLowheight == true || this in lowHeightLetters
|
||||||
|
|
||||||
|
private fun getKerning(prevChar: CodePoint, thisChar: CodePoint): Int {
|
||||||
|
val maskL = glyphProps[prevChar]?.kerningMask
|
||||||
|
val maskR = glyphProps[thisChar]?.kerningMask
|
||||||
|
return if (glyphProps[prevChar]?.hasKernData == true && glyphProps[thisChar]?.hasKernData == true) {
|
||||||
|
val contraction = if (glyphProps[prevChar]?.isKernYtype == true || glyphProps[thisChar]?.isKernYtype == true) -1 else -2
|
||||||
|
kerningRules.forEachIndexed { index, it ->
|
||||||
|
if (it.first.matches(maskL!!) && it.second.matches(maskR!!)) {
|
||||||
|
println("Kerning rule match #${index+1}: ${prevChar.toChar()}${thisChar.toChar()}, Rule:${it.first} ${it.second}; Contraction: ${-contraction}")
|
||||||
|
|
||||||
|
return contraction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
else 0
|
||||||
|
/*else if (prevChar in lowHeightLetters) {
|
||||||
|
return if (thisChar in kernTees) kernTee // lh - T
|
||||||
|
else if (thisChar in kernYees) kernYee // lh - Y
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernElls) {
|
||||||
|
return if (thisChar in kernTees) kernTee // L - T
|
||||||
|
else if (thisChar in kernVees) kernYee // L - V
|
||||||
|
else if (thisChar in kernYees) kernYee // L - Y
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernTees) {
|
||||||
|
return if (thisChar in lowHeightLetters) kernTee // T - lh
|
||||||
|
else if (thisChar in kernJays) kernTee // T - J
|
||||||
|
else if (thisChar in kernAyes) kernYee // T - A
|
||||||
|
else if (thisChar in kernDees) kernTee // T - d
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernYees) {
|
||||||
|
return if (thisChar in lowHeightLetters) kernYee // Y - lh
|
||||||
|
else if (thisChar in kernAyes) kernYee // Y - A
|
||||||
|
else if (thisChar in kernJays) kernYee // Y - J
|
||||||
|
else if (thisChar in kernDees) kernYee // Y - d
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernAyes) {
|
||||||
|
return if (thisChar in kernVees) kernAV // A - V
|
||||||
|
else if (thisChar in kernTees) kernAV // A - T
|
||||||
|
else if (thisChar in kernYees) kernYee // A - Y
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernVees) {
|
||||||
|
return if (thisChar in kernAyes) kernAV // V - A
|
||||||
|
else if (thisChar in kernJays) kernAV // V - J
|
||||||
|
else if (thisChar in kernDees) kernAV // V - d
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernGammas) {
|
||||||
|
return if (thisChar in kernAyes) kernYee // Γ - Α
|
||||||
|
else if (thisChar in lowHeightLetters) kernTee // Γ - lh
|
||||||
|
else if (thisChar in kernJays) kernTee // Γ - J
|
||||||
|
else if (thisChar in kernDees) kernTee // Γ - d
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernBees) {
|
||||||
|
return if (thisChar in kernTees) kernTee // b - T
|
||||||
|
else if (thisChar in kernYees) kernYee // b - Y
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernLowVees) {
|
||||||
|
return if (thisChar in kernTees) kernTee
|
||||||
|
else if (thisChar in kernLowLambdas) kernAVlow
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in kernLowLambdas) {
|
||||||
|
return if (thisChar in kernTees) kernTee
|
||||||
|
else if (thisChar in kernLowVees) kernAVlow
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else if (prevChar in slashes) {
|
||||||
|
return if (thisChar in kernDees || thisChar in lowHeightLetters) kernSlash // / - d
|
||||||
|
else if (thisChar in slashes) kernDoubleSlash
|
||||||
|
else 0
|
||||||
|
}
|
||||||
|
else 0*/
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private fun Boolean.toSign() = if (this) 1 else -1
|
private fun Boolean.toSign() = if (this) 1 else -1
|
||||||
@@ -1344,7 +1444,6 @@ class TerrarumSansBitmap(
|
|||||||
/**
|
/**
|
||||||
* lowercase AND the height is equal to x-height (e.g. lowercase B, D, F, H, K, L, ... does not count
|
* lowercase AND the height is equal to x-height (e.g. lowercase B, D, F, H, K, L, ... does not count
|
||||||
*/
|
*/
|
||||||
fun CodePoint.isLowHeight() = this in lowHeightLetters
|
|
||||||
|
|
||||||
data class ShittyGlyphLayout(val textBuffer: CodepointSequence, val linotype: Texture, val width: Int)
|
data class ShittyGlyphLayout(val textBuffer: CodepointSequence, val linotype: Texture, val width: Int)
|
||||||
data class TextCacheObj(val hash: Long, val glyphLayout: ShittyGlyphLayout?): Comparable<TextCacheObj> {
|
data class TextCacheObj(val hash: Long, val glyphLayout: ShittyGlyphLayout?): Comparable<TextCacheObj> {
|
||||||
@@ -1358,7 +1457,6 @@ class TerrarumSansBitmap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private val HCF = 0x115F
|
private val HCF = 0x115F
|
||||||
private val HJF = 0x1160
|
private val HJF = 0x1160
|
||||||
|
|
||||||
@@ -1813,74 +1911,6 @@ print(','.join(a))
|
|||||||
private val kernSlash = -1
|
private val kernSlash = -1
|
||||||
private val kernDoubleSlash = -2
|
private val kernDoubleSlash = -2
|
||||||
|
|
||||||
private fun getKerning(prevChar: CodePoint, thisChar: CodePoint): Int {
|
|
||||||
return if (prevChar in lowHeightLetters) {
|
|
||||||
return if (thisChar in kernTees) kernTee // lh - T
|
|
||||||
else if (thisChar in kernYees) kernYee // lh - Y
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernElls) {
|
|
||||||
return if (thisChar in kernTees) kernTee // L - T
|
|
||||||
else if (thisChar in kernVees) kernYee // L - V
|
|
||||||
else if (thisChar in kernYees) kernYee // L - Y
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernTees) {
|
|
||||||
return if (thisChar in lowHeightLetters) kernTee // T - lh
|
|
||||||
else if (thisChar in kernJays) kernTee // T - J
|
|
||||||
else if (thisChar in kernAyes) kernYee // T - A
|
|
||||||
else if (thisChar in kernDees) kernTee // T - d
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernYees) {
|
|
||||||
return if (thisChar in lowHeightLetters) kernYee // Y - lh
|
|
||||||
else if (thisChar in kernAyes) kernYee // Y - A
|
|
||||||
else if (thisChar in kernJays) kernYee // Y - J
|
|
||||||
else if (thisChar in kernDees) kernYee // Y - d
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernAyes) {
|
|
||||||
return if (thisChar in kernVees) kernAV // A - V
|
|
||||||
else if (thisChar in kernTees) kernAV // A - T
|
|
||||||
else if (thisChar in kernYees) kernYee // A - Y
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernVees) {
|
|
||||||
return if (thisChar in kernAyes) kernAV // V - A
|
|
||||||
else if (thisChar in kernJays) kernAV // V - J
|
|
||||||
else if (thisChar in kernDees) kernAV // V - d
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernGammas) {
|
|
||||||
return if (thisChar in kernAyes) kernYee // Γ - Α
|
|
||||||
else if (thisChar in lowHeightLetters) kernTee // Γ - lh
|
|
||||||
else if (thisChar in kernJays) kernTee // Γ - J
|
|
||||||
else if (thisChar in kernDees) kernTee // Γ - d
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernBees) {
|
|
||||||
return if (thisChar in kernTees) kernTee // b - T
|
|
||||||
else if (thisChar in kernYees) kernYee // b - Y
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernLowVees) {
|
|
||||||
return if (thisChar in kernTees) kernTee
|
|
||||||
else if (thisChar in kernLowLambdas) kernAVlow
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in kernLowLambdas) {
|
|
||||||
return if (thisChar in kernTees) kernTee
|
|
||||||
else if (thisChar in kernLowVees) kernAVlow
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else if (prevChar in slashes) {
|
|
||||||
return if (thisChar in kernDees || thisChar in lowHeightLetters) kernSlash // / - d
|
|
||||||
else if (thisChar in slashes) kernDoubleSlash
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
else 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val charsetOverrideDefault = Character.toChars(CHARSET_OVERRIDE_DEFAULT).toSurrogatedString()
|
val charsetOverrideDefault = Character.toChars(CHARSET_OVERRIDE_DEFAULT).toSurrogatedString()
|
||||||
val charsetOverrideBulgarian = Character.toChars(CHARSET_OVERRIDE_BG_BG).toSurrogatedString()
|
val charsetOverrideBulgarian = Character.toChars(CHARSET_OVERRIDE_BG_BG).toSurrogatedString()
|
||||||
@@ -1890,6 +1920,65 @@ print(','.join(a))
|
|||||||
private fun CharArray.toSurrogatedString(): String = "${this[0]}${this[1]}"
|
private fun CharArray.toSurrogatedString(): String = "${this[0]}${this[1]}"
|
||||||
|
|
||||||
val noColorCode = toColorCode(0x0000)
|
val noColorCode = toColorCode(0x0000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The "Keming" Machine //
|
||||||
|
|
||||||
|
private val kemingBitMask: IntArray = intArrayOf(7,6,5,4,3,2,1,0,15,14).map { 1 shl it }.toIntArray()
|
||||||
|
|
||||||
|
private class RuleMask(s: String) {
|
||||||
|
|
||||||
|
private var careBits = 0
|
||||||
|
private var ruleBits = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
s.forEachIndexed { index, char ->
|
||||||
|
when (char) {
|
||||||
|
'@' -> {
|
||||||
|
careBits = careBits or kemingBitMask[index]
|
||||||
|
ruleBits = ruleBits or kemingBitMask[index]
|
||||||
|
}
|
||||||
|
'`' -> {
|
||||||
|
careBits = careBits or kemingBitMask[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun matches(shapeBits: Int) = ((shapeBits and careBits) == ruleBits)
|
||||||
|
|
||||||
|
override fun toString() = "C:${careBits.toString(2).padStart(16,'0')}-R:${ruleBits.toString(2).padStart(16,'0')}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legend: _ dont care
|
||||||
|
* @ must have a bit set
|
||||||
|
* ` must have a bit unset
|
||||||
|
* Order: ABCDEFGHJK, where
|
||||||
|
*
|
||||||
|
* A·B < unset for lowheight miniscules, as in e
|
||||||
|
* |·| < space we don't care
|
||||||
|
* C·D < middle hole for majuscules, as in C
|
||||||
|
* E·F < middle hole for miniscules, as in c
|
||||||
|
* G·H
|
||||||
|
*――― < baseline
|
||||||
|
* |·|
|
||||||
|
* J·K
|
||||||
|
*/
|
||||||
|
private val kerningRules = arrayOf(
|
||||||
|
RuleMask("_@_`___`__") to RuleMask("`_________"),
|
||||||
|
RuleMask("_@_@___`__") to RuleMask("`___`_@___"),
|
||||||
|
RuleMask("___`_`____") to RuleMask("`___@_`___"),
|
||||||
|
RuleMask("___`_`____") to RuleMask("`_@___`___"),
|
||||||
|
|
||||||
|
RuleMask("_`________") to RuleMask("@_`___`___"),
|
||||||
|
RuleMask("_`___`_@__") to RuleMask("@_@___`___"),
|
||||||
|
RuleMask("_`___@_`__") to RuleMask("__`_`_____"),
|
||||||
|
RuleMask("_`_@___`__") to RuleMask("__`_`_____"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// End of the Keming Machine
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ import com.badlogic.gdx.graphics.Texture
|
|||||||
import com.badlogic.gdx.graphics.g2d.Batch
|
import com.badlogic.gdx.graphics.g2d.Batch
|
||||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
import net.torvald.terrarumsansbitmap.GlyphProps
|
import net.torvald.terrarumsansbitmap.GlyphProps
|
||||||
import net.torvald.terrarumsansbitmap.gdx.*
|
import net.torvald.terrarumsansbitmap.gdx.*
|
||||||
import net.torvald.terrarumsansbitmap.gdx.CodePoint
|
import net.torvald.terrarumsansbitmap.gdx.CodePoint
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.TextCacheObj
|
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.TextCacheObj
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.ShittyGlyphLayout
|
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.ShittyGlyphLayout
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.isLowHeight
|
|
||||||
import java.io.BufferedOutputStream
|
import java.io.BufferedOutputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
|
|||||||