diff --git a/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm b/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm index b4cf182..37c80ec 100644 --- a/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm @@ -30,6 +30,12 @@ export namespace Crafter { Right }; + enum class TextVerticalAlignment { + Top, + Center, + Bottom + }; + enum class TextOverflowMode { Clip, Wrap diff --git a/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm b/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm index 620a328..aad409a 100644 --- a/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm @@ -358,30 +358,39 @@ export namespace Crafter { } } - void RenderText(std::span 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 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,12 +456,21 @@ 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; }