implementation of "replacewith" compiler directive

This commit is contained in:
minjaesong
2021-12-08 11:12:05 +09:00
parent 5469b56841
commit 0943d38926
12 changed files with 76 additions and 47 deletions

View File

@@ -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

Binary file not shown.

Binary file not shown.

View File

@@ -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)
} }

View File

@@ -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
} }

View File

@@ -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)}")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,22 +1,9 @@
To ถูกตำรว
uu ถูกตรว
Td aำ
mm แป้นพิมพ์เกษมณี แป้นพิมพ์ปัตตะโชติ
Ye คำเตือน-อนามัยและความปลอดภัย
Yd
/œ̃/ UIJTuijt
/ɛ̃/
/ẽ
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.