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 Right
}; };
enum class TextVerticalAlignment {
Top,
Center,
Bottom
};
enum class TextOverflowMode { enum class TextOverflowMode {
Clip, Clip,
Wrap 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); float scale = stbtt_ScaleForPixelHeight(&font.font, size);
int baseline = (int)(font.ascent * scale); int baseline = (int)(font.ascent * scale);
std::uint32_t lineHeight = (font.ascent - font.descent) * scale; std::uint32_t lineHeight = (font.ascent - font.descent) * scale;
std::uint32_t currentY = baseline; std::uint32_t currentY = baseline;
for(std::string_view line : lines) { for(std::string_view line : lines) {
std::uint32_t lineWidth = 0; std::int32_t lineWidth = 0;
for (const char c : line) { for (const char c : line) {
int advance, lsb; int advance, lsb;
stbtt_GetCodepointHMetrics(&font.font, c, &advance, &lsb); stbtt_GetCodepointHMetrics(&font.font, c, &advance, &lsb);
lineWidth += (int)(advance * scale); lineWidth += (int)(advance * scale);
} }
std::uint32_t x = 0;
switch (alignment) { switch (alignment) {
case TextAlignment::Left: case TextAlignment::Left:
x = 0;
break; break;
case TextAlignment::Center: case TextAlignment::Center:
x = (this->scaled.size.x - lineWidth) / 2; offsetX -= lineWidth / 2;
break; break;
case TextAlignment::Right: 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; break;
} }
@ -411,7 +420,7 @@ export namespace Crafter {
case OpaqueType::FullyOpaque: { case OpaqueType::FullyOpaque: {
for (int j = 0; j < h; j++) { for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) { 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; int bufferY = currentY + j + c_y1 + offsetY;
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) { if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) {
@ -425,7 +434,7 @@ export namespace Crafter {
case OpaqueType::Transparent: { case OpaqueType::Transparent: {
for (int j = 0; j < h; j++) { for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) { 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; int bufferY = currentY + j + c_y1 + offsetY;
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) { 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) { if (p + 1 < end) {
int next; int next;
x += (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, utf8_decode(p+1, &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; currentY += lineHeight;