text rendering fixes

This commit is contained in:
Jorijn van der Graaf 2026-04-15 19:30:21 +02:00
commit ef8d623525
2 changed files with 37 additions and 13 deletions

View file

@ -30,6 +30,12 @@ export namespace Crafter {
Right
};
enum class TextVerticalAlignment {
Top,
Center,
Bottom
};
enum class TextOverflowMode {
Clip,
Wrap

View file

@ -358,30 +358,39 @@ export namespace Crafter {
}
}
void RenderText(std::span<const std::string_view> lines, float size, Vector<_Float16, 4> color, Font& font, std::uint8_t frame, TextAlignment alignment = TextAlignment::Left, std::uint32_t offsetX = 0, std::uint32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) requires(Mapped) {
void RenderText(std::span<const std::string_view> lines, float size, Vector<_Float16, 4> color, Font& font, std::uint8_t frame, TextAlignment alignment = TextAlignment::Left, TextVerticalAlignment verticalAlignment = TextVerticalAlignment::Top, std::int32_t offsetX = 0, std::int32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) requires(Mapped) {
float scale = stbtt_ScaleForPixelHeight(&font.font, size);
int baseline = (int)(font.ascent * scale);
std::uint32_t lineHeight = (font.ascent - font.descent) * scale;
std::uint32_t currentY = baseline;
for(std::string_view line : lines) {
std::uint32_t lineWidth = 0;
std::int32_t lineWidth = 0;
for (const char c : line) {
int advance, lsb;
stbtt_GetCodepointHMetrics(&font.font, c, &advance, &lsb);
lineWidth += (int)(advance * scale);
}
std::uint32_t x = 0;
switch (alignment) {
case TextAlignment::Left:
x = 0;
break;
case TextAlignment::Center:
x = (this->scaled.size.x - lineWidth) / 2;
offsetX -= lineWidth / 2;
break;
case TextAlignment::Right:
x = this->scaled.size.x - lineWidth;
offsetX += lineWidth;
break;
}
switch (verticalAlignment) {
case TextVerticalAlignment::Top:
break;
case TextVerticalAlignment::Center:
offsetY += (lineHeight / 2) - (size);
break;
case TextVerticalAlignment::Bottom:
offsetY += lineHeight;
break;
}
@ -411,7 +420,7 @@ export namespace Crafter {
case OpaqueType::FullyOpaque: {
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
int bufferX = x + i + c_x1 + offsetX;
int bufferX = offsetX + i + c_x1;
int bufferY = currentY + j + c_y1 + offsetY;
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) {
@ -425,7 +434,7 @@ export namespace Crafter {
case OpaqueType::Transparent: {
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
int bufferX = x + i + c_x1 + offsetX;
int bufferX = offsetX + i + c_x1;
int bufferY = currentY + j + c_y1 + offsetY;
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) {
@ -447,11 +456,20 @@ export namespace Crafter {
}
}
x += (int)(ax * scale);
if(alignment != TextAlignment::Right) {
offsetX += (int)(ax * scale);
if (p + 1 < end) {
int next;
x += (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, utf8_decode(p+1, &next));
if (p + 1 < end) {
int next;
offsetX += (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, utf8_decode(p+1, &next));
}
} else {
offsetX -= (int)(ax * scale);
if (p + 1 < end) {
int next;
offsetX -= (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, utf8_decode(p+1, &next));
}
}
}
currentY += lineHeight;