mirror of
https://github.com/curioustorvald/Terrarum-sans-bitmap.git
synced 2026-03-07 11:51:50 +09:00
implementation of "replacewith" compiler directive
This commit is contained in:
@@ -49,12 +49,12 @@ Rightmost vertical column (should be 20 px tall) contains the tags. Tags are def
|
|||||||
m --Is this character lowheight?
|
m --Is this character lowheight?
|
||||||
K -,
|
K -,
|
||||||
K |= Tags used by the "Keming Machine"
|
K |= Tags used by the "Keming Machine"
|
||||||
K |
|
K -'
|
||||||
K -' ,- Nudging Bits (see below)
|
Q ---Compiler Directive (see below)
|
||||||
n --'
|
n --,
|
||||||
X -,
|
X -, `-Nudging Bits (see below)
|
||||||
X |= Diacritics Anchor Points (see below)
|
|
||||||
X |
|
X |
|
||||||
|
X |= Diacritics Anchor Points (see below)
|
||||||
X -'
|
X -'
|
||||||
A -,_ 0 Align 1 Align 0 Align 1 Align before
|
A -,_ 0 Align 1 Align 0 Align 1 Align before
|
||||||
A -' 0 left 0 right 1 centre 1 the glyph
|
A -' 0 left 0 right 1 centre 1 the glyph
|
||||||
@@ -93,6 +93,20 @@ MSB for each word must be set so that the pixel would appear brighter on the ima
|
|||||||
|
|
||||||
Right now, only the type-0 diacritics and its anchor point is used by the font.
|
Right now, only the type-0 diacritics and its anchor point is used by the font.
|
||||||
|
|
||||||
|
* Compiler Directives:
|
||||||
|
|
||||||
|
<MSB,Red> [Opcode] [arg1] [arg2] <LSB,Blue>
|
||||||
|
|
||||||
|
Currently supported opcodes:
|
||||||
|
|
||||||
|
- 00000000: No-operation; does not use the Compiler Directive system.
|
||||||
|
|
||||||
|
- 10000xxx: Replace a character with xxx subchars (yes, number 0 can be used).
|
||||||
|
Replacement characters are encoded vertically from X-zero, bit by bit
|
||||||
|
(colour of the pixel doesn't matter) with LSB sitting on Y-zero.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-= NOTE =-
|
-= NOTE =-
|
||||||
|
|
||||||
The code has remnants of one old HACK: using 0th diacritics' X-anchor pos as a type selector
|
The code has remnants of one old HACK: using 0th diacritics' X-anchor pos as a type selector
|
||||||
@@ -102,7 +116,6 @@ Interpretation:
|
|||||||
DIA_OVERLAY = 1
|
DIA_OVERLAY = 1
|
||||||
DIA_JOINER = 2
|
DIA_JOINER = 2
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Stack Up/Down
|
#### Stack Up/Down
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 131 B |
BIN
assets/latinExtA_variable.tga
LFS
BIN
assets/latinExtA_variable.tga
LFS
Binary file not shown.
BIN
assets/latinExtB_variable.tga
LFS
BIN
assets/latinExtB_variable.tga
LFS
Binary file not shown.
@@ -23,12 +23,16 @@ data class GlyphProps(
|
|||||||
|
|
||||||
val stackWhere: Int = 0, // STACK_UP..STACK_UP_N_DOWN
|
val stackWhere: Int = 0, // STACK_UP..STACK_UP_N_DOWN
|
||||||
|
|
||||||
val extInfo: IntArray = DEFAULT_EXTINFO,
|
val extInfo: IntArray = IntArray(15),
|
||||||
|
|
||||||
val hasKernData: Boolean = false,
|
val hasKernData: Boolean = false,
|
||||||
val isKernYtype: Boolean = false,
|
val isKernYtype: Boolean = false,
|
||||||
val kerningMask: Int = 255,
|
val kerningMask: Int = 255,
|
||||||
|
|
||||||
|
val directiveOpcode: Int = 0, // 8-bits wide
|
||||||
|
val directiveArg1: Int = 0, // 8-bits wide
|
||||||
|
val directiveArg2: Int = 0, // 8-bits wide
|
||||||
|
|
||||||
val rtl: Boolean = false,
|
val rtl: Boolean = false,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -46,8 +50,6 @@ data class GlyphProps(
|
|||||||
const val DIA_JOINER = 2
|
const val DIA_JOINER = 2
|
||||||
|
|
||||||
private fun Boolean.toInt() = if (this) 1 else 0
|
private fun Boolean.toInt() = if (this) 1 else 0
|
||||||
|
|
||||||
val DEFAULT_EXTINFO = IntArray(15)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*constructor(width: Int, tags: Int) : this(
|
/*constructor(width: Int, tags: Int) : this(
|
||||||
@@ -109,5 +111,18 @@ data class GlyphProps(
|
|||||||
return other is GlyphProps && this.hashCode() == other.hashCode()
|
return other is GlyphProps && this.hashCode() == other.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requiredExtInfoCount() = if (stackWhere == STACK_BEFORE_N_AFTER) 2 else 0
|
fun requiredExtInfoCount() =
|
||||||
|
if (stackWhere == STACK_BEFORE_N_AFTER)
|
||||||
|
2
|
||||||
|
else if (directiveOpcode in 0b10000_000..0b10000_111)
|
||||||
|
directiveOpcode and 7
|
||||||
|
else 0
|
||||||
|
|
||||||
|
fun isPragma(pragma: String) = when (pragma) {
|
||||||
|
"replacewith" -> directiveOpcode in 0b10000_000..0b10000_111
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEachExtInfo(action: (Int) -> Unit) = extInfo.slice(0 until requiredExtInfoCount()).forEach(action)
|
||||||
|
fun forEachExtInfoIndexed(action: (Int, Int) -> Unit) = extInfo.slice(0 until requiredExtInfoCount()).forEachIndexed(action)
|
||||||
}
|
}
|
||||||
@@ -702,6 +702,7 @@ class TerrarumSansBitmap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Boolean.toInt() = if (this) 1 else 0
|
private fun Boolean.toInt() = if (this) 1 else 0
|
||||||
|
/** @return THIRTY-TWO bit number: this includes alpha channel value; or 0 if alpha is zero */
|
||||||
private fun Int.tagify() = if (this and 255 == 0) 0 else this
|
private fun Int.tagify() = if (this and 255 == 0) 0 else this
|
||||||
|
|
||||||
private fun buildWidthTable(pixmap: Pixmap, codeRange: Iterable<Int>, cols: Int = 16) {
|
private fun buildWidthTable(pixmap: Pixmap, codeRange: Iterable<Int>, cols: Int = 16) {
|
||||||
@@ -725,7 +726,6 @@ class TerrarumSansBitmap(
|
|||||||
val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6).tagify()
|
val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6).tagify()
|
||||||
val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7).tagify()
|
val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7).tagify()
|
||||||
val kerningBit3 = pixmap.getPixel(codeStartX, codeStartY + 8).tagify()
|
val kerningBit3 = pixmap.getPixel(codeStartX, codeStartY + 8).tagify()
|
||||||
val kerningBit4 = pixmap.getPixel(codeStartX, codeStartY + 9).tagify()
|
|
||||||
var isKernYtype = ((kerningBit1 and 0x80000000.toInt()) != 0)
|
var isKernYtype = ((kerningBit1 and 0x80000000.toInt()) != 0)
|
||||||
var kerningMask = kerningBit1.ushr(8).and(0xFFFFFF)
|
var kerningMask = kerningBit1.ushr(8).and(0xFFFFFF)
|
||||||
val hasKernData = kerningBit1 and 255 != 0//(kerningBit1 and 255 != 0 && kerningMask != 0xFFFF)
|
val hasKernData = kerningBit1 and 255 != 0//(kerningBit1 and 255 != 0 && kerningMask != 0xFFFF)
|
||||||
@@ -734,6 +734,12 @@ class TerrarumSansBitmap(
|
|||||||
kerningMask = 255
|
kerningMask = 255
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val compilerDirectives = pixmap.getPixel(codeStartX, codeStartY + 9).tagify()
|
||||||
|
val directiveOpcode = compilerDirectives.ushr(24).and(255)
|
||||||
|
val directiveArg1 = compilerDirectives.ushr(16).and(255)
|
||||||
|
val directiveArg2 = compilerDirectives.ushr(8).and(255)
|
||||||
|
|
||||||
|
|
||||||
val nudgingBits = pixmap.getPixel(codeStartX, codeStartY + 10).tagify()
|
val nudgingBits = pixmap.getPixel(codeStartX, codeStartY + 10).tagify()
|
||||||
val nudgeX = nudgingBits.ushr(24).toByte().toInt() // signed 8-bit int
|
val nudgeX = nudgingBits.ushr(24).toByte().toInt() // signed 8-bit int
|
||||||
val nudgeY = nudgingBits.ushr(16).toByte().toInt() // signed 8-bit int
|
val nudgeY = nudgingBits.ushr(16).toByte().toInt() // signed 8-bit int
|
||||||
@@ -762,7 +768,7 @@ class TerrarumSansBitmap(
|
|||||||
|
|
||||||
val stackWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) }
|
val stackWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) }
|
||||||
|
|
||||||
glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, GlyphProps.DEFAULT_EXTINFO, hasKernData, isKernYtype, kerningMask)
|
glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, IntArray(15), hasKernData, isKernYtype, kerningMask, directiveOpcode, directiveArg1, directiveArg2)
|
||||||
|
|
||||||
// if (nudgingBits != 0) dbgprn("${code.charInfo()} nudgeX=$nudgeX, nudgeY=$nudgeY, nudgingBits=0x${nudgingBits.toString(16)}")
|
// if (nudgingBits != 0) dbgprn("${code.charInfo()} nudgeX=$nudgeX, nudgeY=$nudgeY, nudgingBits=0x${nudgingBits.toString(16)}")
|
||||||
// if (writeOnTop >= 0) dbgprn("WriteOnTop: ${code.charInfo()} (Type-${writeOnTop})")
|
// if (writeOnTop >= 0) dbgprn("WriteOnTop: ${code.charInfo()} (Type-${writeOnTop})")
|
||||||
@@ -770,6 +776,7 @@ class TerrarumSansBitmap(
|
|||||||
// extra info
|
// extra info
|
||||||
val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0
|
val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0
|
||||||
if (extCount > 0) {
|
if (extCount > 0) {
|
||||||
|
|
||||||
for (x in 0 until extCount) {
|
for (x in 0 until extCount) {
|
||||||
var info = 0
|
var info = 0
|
||||||
for (y in 0..18) {
|
for (y in 0..18) {
|
||||||
@@ -781,6 +788,9 @@ class TerrarumSansBitmap(
|
|||||||
|
|
||||||
glyphProps[code]!!.extInfo[x] = info
|
glyphProps[code]!!.extInfo[x] = info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// println("[TerrarumSansBitmap] char with $extCount extra info: ${code.charInfo()}; opcode: ${directiveOpcode.toString(16)}")
|
||||||
|
// println("contents: ${glyphProps[code]!!.extInfo.map { it.toString(16) }.joinToString()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1102,18 +1112,22 @@ class TerrarumSansBitmap(
|
|||||||
else if (diacriticDotRemoval.containsKey(c) && (glyphProps[cNext]?.writeOnTop ?: -1) >= 0 && glyphProps[cNext]?.stackWhere == GlyphProps.STACK_UP) {
|
else if (diacriticDotRemoval.containsKey(c) && (glyphProps[cNext]?.writeOnTop ?: -1) >= 0 && glyphProps[cNext]?.stackWhere == GlyphProps.STACK_UP) {
|
||||||
seq.add(diacriticDotRemoval[c]!!)
|
seq.add(diacriticDotRemoval[c]!!)
|
||||||
}
|
}
|
||||||
// rearrange {letter, before-and-after diacritics} as {letter, before-diacritics, after-diacritics}
|
// rearrange {letter, before-and-after diacritics} as {before-diacritics, letter, after-diacritics}
|
||||||
// {letter, before-diacritics} part will be dealt with swapping code below
|
else if (i < this.lastIndex && glyphProps[this[i + 1]]?.stackWhere == GlyphProps.STACK_BEFORE_N_AFTER) {
|
||||||
// DOES NOT WORK if said diacritics has codepoint > 0xFFFF
|
|
||||||
else if (i < this.lastIndex && this[i + 1] <= 0xFFFF &&
|
|
||||||
glyphProps[this[i + 1]]?.stackWhere == GlyphProps.STACK_BEFORE_N_AFTER) {
|
|
||||||
|
|
||||||
val diacriticsProp = glyphProps[this[i + 1]]!!
|
val diacriticsProp = glyphProps[this[i + 1]]!!
|
||||||
|
seq.add(diacriticsProp.extInfo[0])
|
||||||
seq.add(c)
|
seq.add(c)
|
||||||
seq.add(diacriticsProp.extInfo!![0])
|
seq.add(diacriticsProp.extInfo[1])
|
||||||
seq.add(diacriticsProp.extInfo!![1])
|
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
else if (glyphProps[c]?.isPragma("replacewith") == true) {
|
||||||
|
// println("[TerrarumSansBitmap] replacing ${c.toString(16)} with:")
|
||||||
|
glyphProps[c]!!.forEachExtInfo {
|
||||||
|
// println("${it.charInfo()}")
|
||||||
|
seq.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
// U+007F is DEL originally, but this font stores bitmap of Replacement Character (U+FFFD)
|
// U+007F is DEL originally, but this font stores bitmap of Replacement Character (U+FFFD)
|
||||||
// to this position. This line will replace U+FFFD into U+007F.
|
// to this position. This line will replace U+FFFD into U+007F.
|
||||||
else if (c == 0xFFFD) {
|
else if (c == 0xFFFD) {
|
||||||
@@ -1390,7 +1404,7 @@ class TerrarumSansBitmap(
|
|||||||
if (it.first.matches(maskL!!) && it.second.matches(maskR!!)) {
|
if (it.first.matches(maskL!!) && it.second.matches(maskR!!)) {
|
||||||
val contraction = if (glyphProps[prevChar]?.isKernYtype == true || glyphProps[thisChar]?.isKernYtype == true) it.yy else it.bb
|
val contraction = if (glyphProps[prevChar]?.isKernYtype == true || glyphProps[thisChar]?.isKernYtype == true) it.yy else it.bb
|
||||||
|
|
||||||
// dbgprn("Kerning rule match #${index+1}: ${prevChar.toChar()}${thisChar.toChar()}, Rule:${it.first.s} ${it.second.s}; Contraction: $contraction")
|
dbgprn("Kerning rule match #${index+1}: ${prevChar.toChar()}${thisChar.toChar()}, Rule:${it.first.s} ${it.second.s}; Contraction: $contraction")
|
||||||
|
|
||||||
return -contraction
|
return -contraction
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ class TerrarumTypewriterBitmap(
|
|||||||
|
|
||||||
val stackWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) }
|
val stackWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) }
|
||||||
|
|
||||||
glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, GlyphProps.DEFAULT_EXTINFO, hasKernData, isKernYtype, kerningMask)
|
glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, IntArray(15), hasKernData, isKernYtype, kerningMask)
|
||||||
|
|
||||||
// if (nudgingBits != 0) println("${code.charInfo()} nudgeX=$nudgeX, nudgeY=$nudgeY, nudgingBits=0x${nudgingBits.toString(16)}")
|
// if (nudgingBits != 0) println("${code.charInfo()} nudgeX=$nudgeX, nudgeY=$nudgeY, nudgingBits=0x${nudgingBits.toString(16)}")
|
||||||
|
|
||||||
|
|||||||
BIN
testing.PNG
BIN
testing.PNG
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 16 KiB |
27
testtext.txt
27
testtext.txt
@@ -1,22 +1,9 @@
|
|||||||
To
|
ถูกตำรว
|
||||||
uu
|
ถูกตรว
|
||||||
Td
|
aำ
|
||||||
mm
|
แป้นพิมพ์เกษมณี แป้นพิมพ์ปัตตะโชติ
|
||||||
Ye
|
คำเตือน-อนามัยและความปลอดภัย
|
||||||
Yd
|
|
||||||
|
|
||||||
/œ̃/
|
UIJTuijt
|
||||||
/ɛ̃/
|
|
||||||
ẽ
|
|
||||||
Ẽ
|
|
||||||
/ẽ
|
|
||||||
o̸
|
|
||||||
O̸
|
|
||||||
when the line ends with a diacritics, whole letter wont render
|
|
||||||
if the line starts with a letter-with-diacritic, it will error out
|
|
||||||
|
|
||||||
Lyklaborð
|
|
||||||
https://www.java.com/cov/en/download
|
|
||||||
/a /c /d /e /g /i /j /m /n /o /p /q /r /s /u /v v/ /w /x /y /z
|
|
||||||
germyndurinnkvikkalkul
|
|
||||||
|
|
||||||
|
দৌ ষৌ
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user