Mercurial > games > semicongine
changeset 1417:23b4d8c84501
fix: small offset error with left-bearing when aligning characters
author | sam <sam@basx.dev> |
---|---|
date | Wed, 01 Jan 2025 16:38:27 +0700 |
parents | a4fd9c31a225 |
children | 5bbcd40eb145 |
files | semicongine/text.nim semicongine/text/font.nim |
diffstat | 2 files changed, 21 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/text.nim Wed Jan 01 12:42:43 2025 +0700 +++ b/semicongine/text.nim Wed Jan 01 16:38:27 2025 +0700 @@ -68,6 +68,7 @@ FontObj*[MaxGlyphs: static int] = object advance*: Table[Rune, float32] kerning*: Table[(Rune, Rune), float32] + leftBearing*: Table[Rune, float32] lineAdvance*: float32 lineHeight*: float32 # like lineAdvance - lineGap ascent*: float32 # from baseline to highest glyph @@ -168,8 +169,12 @@ proc textDimension*(font: Font, text: string): Vec2f = textDimension(font, text.toRunes()) +proc textDimension*(textBuffer: TextBuffer, text: string | seq[Rune]): Vec2f = + textDimension(textBuffer.font, text) * textBuffer.baseScale + proc updateGlyphData*(textbuffer: var TextBuffer, textHandle: TextHandle) = assert textHandle.generation == textbuffer.generation + let textI = textHandle.index text = textbuffer.texts[textI].text @@ -177,7 +182,7 @@ anchor = textbuffer.texts[textI].anchor globalScale = textbuffer.texts[textI].scale * textbuffer.baseScale - box = textDimension(textbuffer.font, text) * globalScale + box = textbuffer.textDimension(text) * textbuffer.texts[textI].scale xH = textbuffer.font.xHeight * globalScale aratio = getAspectRatio() origin = vec3( @@ -189,6 +194,9 @@ lineWidths = splitLines(text).toSeq.mapIt(width(textbuffer.font, it) * globalScale) maxWidth = box.x + template leftBearing(r: Rune): untyped = + textbuffer.font.leftBearing.getOrDefault(r, 0) * globalScale + var cursorPos = origin lineI = 0 @@ -201,6 +209,10 @@ of Right: cursorPos.x = origin.x + (maxWidth - lineWidths[lineI]) / aratio + # add left bearing for first character at line start + if text.len > 0: + cursorPos.x = cursorPos.x - leftBearing(text[0]) + var bufferOffset = textbuffer.texts[textI].bufferOffset let bufferEnd = textbuffer.texts[textI].bufferOffset + textbuffer.texts[textI].capacity @@ -217,6 +229,11 @@ cursorPos.x = origin.x + ((maxWidth - lineWidths[lineI]) / aratio * 0.5) of Right: cursorPos.x = origin.x + (maxWidth - lineWidths[lineI]) / aratio + + # add left bearing for first character at line start + if text.len > i + 1: + cursorPos.x = cursorPos.x - leftBearing(text[i + 1]) + cursorPos.y = cursorPos.y - textbuffer.font.lineAdvance * globalScale else: if not text[i].isWhitespace():
--- a/semicongine/text/font.nim Wed Jan 01 12:42:43 2025 +0700 +++ b/semicongine/text/font.nim Wed Jan 01 16:38:27 2025 +0700 @@ -113,7 +113,7 @@ stbtt_GetCodepointHMetrics( addr fi, cint(codePoint), addr advanceUnscaled, addr leftBearingUnscaled ) - var leftBearing = leftBearingUnscaled.float32 * glyph2QuadScale + result.leftBearing[codePoint] = leftBearingUnscaled.float32 * glyph2QuadScale result.advance[codePoint] = advanceUnscaled.float32 * glyph2QuadScale let @@ -123,7 +123,8 @@ bitmapW = float32(bitmaps[i].width) bitmapH = float32(bitmaps[i].height) # divide by lineHeightPixels to get from pixel-space to quad-geometry-space - left = leftBearing + offsetX[codePoint].float32 / lineHeightPixels + left = + result.leftBearing[codePoint] + offsetX[codePoint].float32 / lineHeightPixels right = left + bitmapW / lineHeightPixels top = -offsetY[codePoint].float32 / lineHeightPixels bottom = top - bitmapH / lineHeightPixels