diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8538b7..84cba10 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,17 +50,53 @@ Rightmost vertical column (should be 20 px tall) contains the tags. Tags are def K -, K |= Tags used by the "Keming Machine" K | - K -' ,-Nudging control bit (see below) - N --' - X -, write-on-top and centre-aligned: Align to this X pos of prev char - X | (if this is zero, floorOf(width/2) will be used instead) - X | NOT write-on-top: nudge the texture by this pixels to the - X -' left (if N is unset) or right (if N is set) + K -' ,- Nudging Bits (see below) + n --' + X -, + X |= Diacritics Anchor Points (see below) + X | + 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) + +TODO: +c - Nudging +Y - Anchor point Y for undefined, undefined, undefined +X - Anchor point X for undefined, undefined, undefined +Y - Anchor point Y for centre-aligned diacritics, undefined, undefined +X - Anchor point X for centre-aligned diacritics, undefined, undefined + +* Nudging Bits encoding: + + SXXXXXXX SYYYYYYY 00000000 + +Each X and Y numbers are Signed 8-Bit Integer. +X-positive: nudges towards left +Y-positive: nudges towards up + +* Diacritics Anchor Point Encoding: + + 1Y1Y1Y1Y 1Y2Y2Y2Y 1Y3Y3Y3Y + 1X1X1X1X 1X2X2X2X 1X3X3X3X + +where Red is first, Green is second, Blue is the third diacritics. +MSB for each word must be set to indicate the value is being used. + +-= NOTE =- + +This encoding involves one HACK: using 0th diacritics' X-anchor pos as a type selector +This hack applies only when write-on-top bit is set. +Interpretation: + DIA_OVERLAY = 1 + DIA_JOINER = 2 + +Right now, only the type-0 diacritics anchor point is used by the font. + +TODO: use D-bit to give each diacritic a type + ``` #### Stack Up/Down diff --git a/assets/devanagari_bengali_variable.tga b/assets/devanagari_bengali_variable.tga index 9c993d5..7b9a7cd 100755 Binary files a/assets/devanagari_bengali_variable.tga and b/assets/devanagari_bengali_variable.tga differ diff --git a/assets/diacritical_marks_variable.tga b/assets/diacritical_marks_variable.tga index e749b22..9bcb325 100755 Binary files a/assets/diacritical_marks_variable.tga and b/assets/diacritical_marks_variable.tga differ diff --git a/demo.PNG b/demo.PNG index e775356..9bebe41 100755 Binary files a/demo.PNG and b/demo.PNG differ diff --git a/src/net/torvald/terrarumsansbitmap/GlyphProps.kt b/src/net/torvald/terrarumsansbitmap/GlyphProps.kt index 147a6ef..dac1b8b 100755 --- a/src/net/torvald/terrarumsansbitmap/GlyphProps.kt +++ b/src/net/torvald/terrarumsansbitmap/GlyphProps.kt @@ -1,22 +1,35 @@ package net.torvald.terrarumsansbitmap +/** + * Created by minjaesong on 2021-11-25. + */ +data class DiacriticsAnchor(val type: Int, val x: Int, val y: Int, val xUsed: Boolean, val yUsed: Boolean) /** * Created by minjaesong on 2018-08-07. */ data class GlyphProps( val width: Int, - val writeOnTop: Boolean, - val alignWhere: Int, // ALIGN_LEFT..ALIGN_BEFORE - val alignXPos: Int, // 0..15 or DIA_OVERLAY/DIA_JOINER depends on the context - val rtl: Boolean = false, + + val isLowheight: Boolean = false, + + val nudgeX: Int = 0, + val nudgeY: Int = 0, + + val diacriticsAnchors: Array = Array(6) { DiacriticsAnchor(it, 0, 0, false, false) }, + + val alignWhere: Int = 0, // ALIGN_LEFT..ALIGN_BEFORE + + val writeOnTop: Boolean = false, + val stackWhere: Int = 0, // STACK_UP..STACK_UP_N_DOWN - var nudgeRight: Boolean = false, - var extInfo: IntArray? = null, + + val extInfo: IntArray = DEFAULT_EXTINFO, val hasKernData: Boolean = false, - val isLowheight: Boolean = false, val isKernYtype: Boolean = false, - val kerningMask: Int = 255 + val kerningMask: Int = 255, + + val rtl: Boolean = false, ) { companion object { const val ALIGN_LEFT = 0 @@ -33,9 +46,11 @@ data class GlyphProps( const val DIA_JOINER = 2 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( width, tags.ushr(7).and(1) == 1, tags.ushr(5).and(3), @@ -59,21 +74,30 @@ data class GlyphProps( isLowheight, isKernYtype, kerningMask - ) + )*/ - fun isOverlay() = writeOnTop && alignXPos == 1 +// fun isOverlay() = writeOnTop && alignXPos == 1 override fun hashCode(): Int { - val tags = rtl.toInt() or alignXPos.shl(1) or alignWhere.shl(5) or + val tags = rtl.toInt() or alignWhere.shl(5) or writeOnTop.toInt().shl(7) or stackWhere.shl(8) var hash = -2128831034 - extInfo?.forEach { + extInfo.forEach { hash = hash xor it hash = hash * 16777619 } + diacriticsAnchors.forEach { + hash = hash xor it.type + hash = hash * 16777619 + hash = hash xor (it.x or (if (it.xUsed) 128 else 0)) + hash = hash * 16777619 + hash = hash xor (it.y or (if (it.yUsed) 128 else 0)) + hash = hash * 16777619 + } + hash = hash xor tags hash = hash * 167677619 diff --git a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt index c7b72cf..2b0f727 100755 --- a/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt +++ b/src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt @@ -30,6 +30,7 @@ import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.* import com.badlogic.gdx.utils.GdxRuntimeException +import net.torvald.terrarumsansbitmap.DiacriticsAnchor import net.torvald.terrarumsansbitmap.GlyphProps import java.io.BufferedOutputStream import java.io.FileOutputStream @@ -302,7 +303,7 @@ class TerrarumSansBitmap( // make sure null char is actually null (draws nothing and has zero width) sheets[SHEET_ASCII_VARW].regions[0].setColor(0) sheets[SHEET_ASCII_VARW].regions[0].fill() - glyphProps[0] = GlyphProps(0, 0) + glyphProps[0] = GlyphProps(0) } override fun getLineHeight(): Float = H.toFloat() @@ -331,7 +332,7 @@ class TerrarumSansBitmap( private lateinit var tempLinotype: Texture - private var nullProp = GlyphProps(15, 0) + private var nullProp = GlyphProps(15) private val pixmapOffsetY = 10 @@ -342,6 +343,8 @@ class TerrarumSansBitmap( fun drawNormalised(batch: Batch, codepoints: CodepointSequence, x: Float, y: Float): GlyphLayout? { +// codepoints.forEach { dbgprn("${it.charInfo()} ${glyphProps[it]}") } + // Q&D fix for issue #12 // When the line ends with a diacritics, the whole letter won't render // If the line starts with a letter-with-diacritic, it will error out @@ -696,6 +699,9 @@ class TerrarumSansBitmap( return intArrayOf(sheetX, sheetY) } + private fun Boolean.toInt() = if (this) 1 else 0 + private fun Int.tagify() = if (this and 255 == 0) 0 else this + private fun buildWidthTable(pixmap: Pixmap, codeRange: Iterable, cols: Int = 16) { val binaryCodeOffset = W_VAR_INIT @@ -709,64 +715,63 @@ class TerrarumSansBitmap( val codeStartX = cellX + binaryCodeOffset val codeStartY = cellY - val tagStartY = codeStartY + 10 - var width = 0 - var tags = 0 - - for (y in 0..4) { - // if ALPHA is not zero, assume it's 1 - if (pixmap.getPixel(codeStartX, codeStartY + y).and(0xFF) != 0) { - width = width or (1 shl y) - } - } - - for (y in 0..9) { - // if ALPHA is not zero, assume it's 1 - if (pixmap.getPixel(codeStartX, tagStartY + y).and(0xFF) != 0) { - tags = tags or (1 shl y) - } - } - - - // lowheight bit - val isLowHeight = (pixmap.getPixel(codeStartX, codeStartY + 5).and(0xFF) != 0) + val width = (0..4).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y).and(255) != 0).toInt() shl y) } + val isLowHeight = (pixmap.getPixel(codeStartX, codeStartY + 5).and(255) != 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) + val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6).tagify() + val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7).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 kerningMask = kerningBit1.ushr(8).and(0xFFFFFF) + val hasKernData = kerningBit1 and 255 != 0//(kerningBit1 and 255 != 0 && kerningMask != 0xFFFF) + if (!hasKernData) { + isKernYtype = false + kerningMask = 255 + } + val nudgingBits = pixmap.getPixel(codeStartX, codeStartY + 10).tagify() + val nudgeX = nudgingBits.ushr(24).toByte().toInt() // signed 8-bit int + val nudgeY = nudgingBits.ushr(16).toByte().toInt() // signed 8-bit int - //dbgprn("$code: Width $width, tags $tags") - if (hasKerningBit) - dbgprn("U+${code.toString(16).padStart(4, '0').toUpperCase()}: W $width, tags $tags, low? $isLowHeight, kern ${kerningMask.toString(16).padStart(6,'0')} (raw: ${kerningBit1.toLong().and(4294967295).toString(16).padStart(8,'0')})") + val diacriticsAnchors = (0..5).map { + val yPos = 11 + (it / 3) * 2 + val shift = (3 - (it % 3)) * 8 + val yPixel = pixmap.getPixel(codeStartX, codeStartY + yPos).tagify() + val xPixel = pixmap.getPixel(codeStartX, codeStartY + yPos + 1).tagify() + val y = (yPixel ushr shift) and 127 + val x = (xPixel ushr shift) and 127 + val yUsed = (yPixel ushr shift) >= 128 + val xUsed = (yPixel ushr shift) >= 128 - /*val isDiacritics = pixmap.getPixel(codeStartX, codeStartY + H - 1).and(0xFF) != 0 - if (isDiacritics) - glyphWidth = -glyphWidth*/ + DiacriticsAnchor(it, x, y, xUsed, yUsed) + }.toTypedArray() - glyphProps[code] = if (hasKerningBit) GlyphProps(width, tags, isLowHeight, isKerningYtype, kerningMask) else GlyphProps(width, tags) + val alignWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 15).and(255) != 0).toInt() shl y) } + + val writeOnTop = pixmap.getPixel(codeStartX, codeStartY + 17).and(255) != 0 + + 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) + +// if (nudgingBits != 0) dbgprn("${code.charInfo()} nudgeX=$nudgeX, nudgeY=$nudgeY, nudgingBits=0x${nudgingBits.toString(16)}") // extra info val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0 if (extCount > 0) { - - glyphProps[code]?.extInfo = IntArray(extCount) - for (x in 0 until extCount) { var info = 0 for (y in 0..18) { // if ALPHA is not zero, assume it's 1 - if (pixmap.getPixel(cellX + x, cellY + y).and(0xFF) != 0) { + if (pixmap.getPixel(cellX + x, cellY + y).and(255) != 0) { info = info or (1 shl y) } } - glyphProps[code]!!.extInfo!![x] = info + glyphProps[code]!!.extInfo[x] = info } } @@ -775,27 +780,27 @@ class TerrarumSansBitmap( private fun buildWidthTableFixed() { // fixed-width props - codeRange[SHEET_CJK_PUNCT].forEach { glyphProps[it] = GlyphProps(W_ASIAN_PUNCT, 0) } - codeRange[SHEET_CUSTOM_SYM].forEach { glyphProps[it] = GlyphProps(20, 0) } - codeRange[SHEET_FW_UNI].forEach { glyphProps[it] = GlyphProps(W_UNIHAN, 0) } - codeRange[SHEET_HANGUL].forEach { glyphProps[it] = GlyphProps(W_HANGUL_BASE, 0) } - codeRangeHangulCompat.forEach { glyphProps[it] = GlyphProps(W_HANGUL_BASE, 0) } - codeRange[SHEET_KANA].forEach { glyphProps[it] = GlyphProps(W_KANA, 0) } - codeRange[SHEET_RUNIC].forEach { glyphProps[it] = GlyphProps(9, 0) } - codeRange[SHEET_UNIHAN].forEach { glyphProps[it] = GlyphProps(W_UNIHAN, 0) } - (0xD800..0xDFFF).forEach { glyphProps[it] = GlyphProps(0, 0) } - (0x100000..0x10FFFF).forEach { glyphProps[it] = GlyphProps(0, 0) } - (0xFFFA0..0xFFFFF).forEach { glyphProps[it] = GlyphProps(0, 0) } + codeRange[SHEET_CJK_PUNCT].forEach { glyphProps[it] = GlyphProps(W_ASIAN_PUNCT) } + codeRange[SHEET_CUSTOM_SYM].forEach { glyphProps[it] = GlyphProps(20) } + codeRange[SHEET_FW_UNI].forEach { glyphProps[it] = GlyphProps(W_UNIHAN) } + codeRange[SHEET_HANGUL].forEach { glyphProps[it] = GlyphProps(W_HANGUL_BASE) } + codeRangeHangulCompat.forEach { glyphProps[it] = GlyphProps(W_HANGUL_BASE) } + codeRange[SHEET_KANA].forEach { glyphProps[it] = GlyphProps(W_KANA) } + codeRange[SHEET_RUNIC].forEach { glyphProps[it] = GlyphProps(9) } + codeRange[SHEET_UNIHAN].forEach { glyphProps[it] = GlyphProps(W_UNIHAN) } + (0xD800..0xDFFF).forEach { glyphProps[it] = GlyphProps(0) } + (0x100000..0x10FFFF).forEach { glyphProps[it] = GlyphProps(0) } + (0xFFFA0..0xFFFFF).forEach { glyphProps[it] = GlyphProps(0) } // manually add width of one orphan insular letter // WARNING: glyphs in 0xA770..0xA778 has invalid data, further care is required - glyphProps[0x1D79] = GlyphProps(9, 0) + glyphProps[0x1D79] = GlyphProps(9) // U+007F is DEL originally, but this font stores bitmap of Replacement Character (U+FFFD) // to this position. String replacer will replace U+FFFD into U+007F. - glyphProps[0x7F] = GlyphProps(15, 0) + glyphProps[0x7F] = GlyphProps(15) } @@ -884,7 +889,7 @@ class TerrarumSansBitmap( posXbuffer[charIndex] = posXbuffer[nonDiacriticCounter] } else if (!thisProp.writeOnTop) { - posXbuffer[charIndex] = ((if (thisProp.nudgeRight) 1 else -1) * thisProp.alignXPos) + + posXbuffer[charIndex] = -thisProp.nudgeX + when (itsProp.alignWhere) { GlyphProps.ALIGN_RIGHT -> posXbuffer[nonDiacriticCounter] + W_VAR_INIT + alignmentOffset + interchar + kerning + extraWidth @@ -898,9 +903,10 @@ class TerrarumSansBitmap( stackUpwardCounter = 0 stackDownwardCounter = 0 - extraWidth = (if (thisProp.nudgeRight) -1 else 1) * thisProp.alignXPos // NOTE: sign is flipped! + extraWidth = thisProp.nudgeX // NOTE: sign is flipped! } - else if (thisProp.writeOnTop && thisProp.alignXPos == GlyphProps.DIA_JOINER) { + // FIXME HACK: using 0th diacritics' X-anchor pos as a type selector + else if (thisProp.writeOnTop && thisProp.diacriticsAnchors[0].x == GlyphProps.DIA_JOINER) { posXbuffer[charIndex] = when (itsProp.alignWhere) { GlyphProps.ALIGN_RIGHT -> posXbuffer[nonDiacriticCounter] + W_VAR_INIT + alignmentOffset @@ -919,7 +925,7 @@ class TerrarumSansBitmap( posXbuffer[nonDiacriticCounter] - (W_VAR_INIT - itsProp.width) } GlyphProps.ALIGN_CENTRE -> { - val alignXPos = if (itsProp.alignXPos == 0) itsProp.width.div(2) else itsProp.alignXPos + val alignXPos = if (itsProp.diacriticsAnchors[0].x == 0) itsProp.width.div(2) else itsProp.diacriticsAnchors[0].x if (itsProp.alignWhere == GlyphProps.ALIGN_RIGHT) { posXbuffer[nonDiacriticCounter] + alignXPos + (itsProp.width + 1).div(2) @@ -948,7 +954,7 @@ class TerrarumSansBitmap( //dbgprn("AAARRRRHHHH for character ${thisChar.toHex()}") //dbgprn("lastNonDiacriticChar: ${lastNonDiacriticChar.toHex()}") //dbgprn("cond: ${thisProp.alignXPos == GlyphProps.DIA_OVERLAY}, charIndex: $charIndex") - if (thisProp.alignXPos == GlyphProps.DIA_OVERLAY) + if (thisProp.diacriticsAnchors[0].x == GlyphProps.DIA_OVERLAY) posYbuffer[charIndex] -= H_OVERLAY_LOWERCASE_SHIFTDOWN * (!flipY).toSign() // if minus-assign doesn't work, try plus-assign else posYbuffer[charIndex] -= H_STACKUP_LOWERCASE_SHIFTDOWN * (!flipY).toSign() // if minus-assign doesn't work, try plus-assign @@ -978,10 +984,10 @@ class TerrarumSansBitmap( 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 + (lastCharProp.width).div(2) + penultCharProp.diacriticsAnchors[0].x } else if (lastCharProp.alignWhere == GlyphProps.ALIGN_RIGHT) { - (lastCharProp.width) + penultCharProp.alignXPos + (lastCharProp.width) + penultCharProp.diacriticsAnchors[0].x } else 0 diff --git a/src/net/torvald/terrarumtypewriterbitmap/gdx/TerrarumTypewriterBitmap.kt b/src/net/torvald/terrarumtypewriterbitmap/gdx/TerrarumTypewriterBitmap.kt index 47e5a9d..3ae328a 100644 --- a/src/net/torvald/terrarumtypewriterbitmap/gdx/TerrarumTypewriterBitmap.kt +++ b/src/net/torvald/terrarumtypewriterbitmap/gdx/TerrarumTypewriterBitmap.kt @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.g2d.Batch import com.badlogic.gdx.graphics.g2d.BitmapFont import com.badlogic.gdx.graphics.g2d.GlyphLayout import com.badlogic.gdx.utils.GdxRuntimeException +import net.torvald.terrarumsansbitmap.DiacriticsAnchor import net.torvald.terrarumsansbitmap.GlyphProps import net.torvald.terrarumsansbitmap.gdx.* import net.torvald.terrarumsansbitmap.gdx.CodePoint @@ -178,7 +179,7 @@ class TerrarumTypewriterBitmap( pixmap.dispose() // you are terminated } - glyphProps[0] = GlyphProps(0, 0) + glyphProps[0] = GlyphProps(0) } @@ -188,6 +189,8 @@ class TerrarumTypewriterBitmap( intArrayOf(coff % 16, coff / 16) } + private fun Boolean.toInt() = if (this) 1 else 0 + private fun Int.tagify() = if (this and 255 == 0) 0 else this private fun buildWidthTable(pixmap: Pixmap, codeRange: Iterable, cols: Int = 16) { val binaryCodeOffset = TerrarumSansBitmap.W_VAR_INIT @@ -202,53 +205,65 @@ class TerrarumTypewriterBitmap( val codeStartX = cellX + binaryCodeOffset val codeStartY = cellY - val tagStartY = codeStartY + 10 - var width = 0 - var tags = 0 + val width = (0..4).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y).and(255) != 0).toInt() shl y) } + val isLowHeight = (pixmap.getPixel(codeStartX, codeStartY + 5).and(255) != 0) - for (y in 0..3) { - // if ALPHA is not zero, assume it's 1 - if (pixmap.getPixel(codeStartX, codeStartY + y).and(0xFF) != 0) { - width = width or (1 shl y) - } + // Keming machine parameters + val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6).tagify() + val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7).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 kerningMask = kerningBit1.ushr(8).and(0xFFFFFF) + val hasKernData = kerningBit1 and 255 != 0//(kerningBit1 and 255 != 0 && kerningMask != 0xFFFF) + if (!hasKernData) { + isKernYtype = false + kerningMask = 255 } - for (y in 0..9) { - // if ALPHA is not zero, assume it's 1 - if (pixmap.getPixel(codeStartX, tagStartY + y).and(0xFF) != 0) { - tags = tags or (1 shl y) - } - } + val nudgingBits = pixmap.getPixel(codeStartX, codeStartY + 10).tagify() + val nudgeX = nudgingBits.ushr(16).toByte().toInt() // signed 8-bit int + val nudgeY = nudgingBits.ushr(8).toByte().toInt() // signed 8-bit int - if (code and 127 == 67) width *= -1 // the backspace key - if (debug) println("${code.charInfo()}: Width $width, tags $tags") + val diacriticsAnchors = (0..5).map { + val yPos = 11 + (it / 3) + val shift = (2 - (it % 3)) * 8 + val yPixel = pixmap.getPixel(codeStartX, codeStartY + yPos).tagify() + val xPixel = pixmap.getPixel(codeStartX, codeStartY + yPos + 1).tagify() + val y = (yPixel ushr shift) and 127 + val x = (xPixel ushr shift) and 127 + val yUsed = (yPixel ushr shift) >= 128 + val xUsed = (yPixel ushr shift) >= 128 - /*val isDiacritics = pixmap.getPixel(codeStartX, codeStartY + H - 1).and(0xFF) != 0 - if (isDiacritics) - glyphWidth = -glyphWidth*/ + DiacriticsAnchor(it, x, y, xUsed, yUsed) + }.toTypedArray() + val alignWhere = (11..12).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y).and(255) != 0).toInt() shl y) } - glyphProps[code] = GlyphProps(width, tags) + val writeOnTop = pixmap.getPixel(codeStartX, codeStartY + 13).and(255) != 0 + + val stackWhere = (14..15).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y).and(255) != 0).toInt() shl y) } + + glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, GlyphProps.DEFAULT_EXTINFO, hasKernData, isKernYtype, kerningMask) +// if (code < 256) dbgprn("${code.charInfo()} width: $width, tags: ${glyphProps[code]}") // extra info val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0 if (extCount > 0) { - - glyphProps[code]?.extInfo = IntArray(extCount) - for (x in 0 until extCount) { var info = 0 for (y in 0..18) { // if ALPHA is not zero, assume it's 1 - if (pixmap.getPixel(cellX + x, cellY + y).and(0xFF) != 0) { + if (pixmap.getPixel(cellX + x, cellY + y).and(255) != 0) { info = info or (1 shl y) } } - glyphProps[code]!!.extInfo!![x] = info + glyphProps[code]!!.extInfo[x] = info } } + } } @@ -257,7 +272,7 @@ class TerrarumTypewriterBitmap( private var flagFirstRun = true private var textBuffer = CodepointSequence(256) private lateinit var tempLinotype: Texture - private var nullProp = GlyphProps(15, 0) + private var nullProp = GlyphProps(15) fun draw(batch: Batch, codepoints: CodepointSequence, x: Float, y: Float): GlyphLayout? { @@ -424,7 +439,7 @@ class TerrarumTypewriterBitmap( if (!thisProp.writeOnTop) { - posXbuffer[charIndex] = ((if (thisProp.nudgeRight) 1 else -1) * thisProp.alignXPos) + + posXbuffer[charIndex] = thisProp.nudgeX + when (itsProp.alignWhere) { GlyphProps.ALIGN_RIGHT -> posXbuffer[nonDiacriticCounter] + TerrarumSansBitmap.W_VAR_INIT + alignmentOffset + interchar + kerning + extraWidth @@ -438,9 +453,9 @@ class TerrarumTypewriterBitmap( stackUpwardCounter = 0 stackDownwardCounter = 0 - extraWidth = (if (thisProp.nudgeRight) -1 else 1) * thisProp.alignXPos // NOTE: sign is flipped! + extraWidth = -thisProp.nudgeX // NOTE: sign is flipped! } - else if (thisProp.writeOnTop && thisProp.alignXPos == GlyphProps.DIA_JOINER) { + else if (thisProp.writeOnTop && thisProp.diacriticsAnchors[0].x == GlyphProps.DIA_JOINER) { posXbuffer[charIndex] = when (itsProp.alignWhere) { GlyphProps.ALIGN_RIGHT -> posXbuffer[nonDiacriticCounter] + TerrarumSansBitmap.W_VAR_INIT + alignmentOffset @@ -459,7 +474,7 @@ class TerrarumTypewriterBitmap( posXbuffer[nonDiacriticCounter] - (TerrarumSansBitmap.W_VAR_INIT - itsProp.width) } GlyphProps.ALIGN_CENTRE -> { - val alignXPos = if (itsProp.alignXPos == 0) itsProp.width.div(2) else itsProp.alignXPos + val alignXPos = if (itsProp.diacriticsAnchors[0].x == 0) itsProp.width.div(2) else itsProp.diacriticsAnchors[0].x if (itsProp.alignWhere == GlyphProps.ALIGN_RIGHT) { posXbuffer[nonDiacriticCounter] + alignXPos + (itsProp.width + 1).div(2) @@ -516,10 +531,10 @@ class TerrarumTypewriterBitmap( 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 + (lastCharProp.width).div(2) + penultCharProp.diacriticsAnchors[0].x } else if (lastCharProp.alignWhere == GlyphProps.ALIGN_RIGHT) { - (lastCharProp.width) + penultCharProp.alignXPos + (lastCharProp.width) + penultCharProp.diacriticsAnchors[0].x } else 0 diff --git a/testing.PNG b/testing.PNG index d3af9a0..edbaa2c 100755 Binary files a/testing.PNG and b/testing.PNG differ diff --git a/work_files/devanagari_bengali_variable.psd b/work_files/devanagari_bengali_variable.psd index dba30cc..918d41b 100644 Binary files a/work_files/devanagari_bengali_variable.psd and b/work_files/devanagari_bengali_variable.psd differ diff --git a/work_files/diacritical_marks_variable.psd b/work_files/diacritical_marks_variable.psd index 0f0d7ab..784ef18 100644 Binary files a/work_files/diacritical_marks_variable.psd and b/work_files/diacritical_marks_variable.psd differ