From 5b081c0b0be025c9c46b651bdf40bb9123c2259b Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Mon, 20 Jul 2026 10:39:20 +0800 Subject: [PATCH] feat(ui): add word wrap for chat messages with font width measurement --- include/Cubed/tools/font.hpp | 1 + include/Cubed/ui/chat_box.hpp | 1 + src/tools/font.cpp | 22 +++++++++++++++++++ src/ui/chat_box.cpp | 40 +++++++++++++++++++++++++++++++++-- 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/include/Cubed/tools/font.hpp b/include/Cubed/tools/font.hpp index 55d6d7f..27c823f 100644 --- a/include/Cubed/tools/font.hpp +++ b/include/Cubed/tools/font.hpp @@ -56,6 +56,7 @@ public: TextMesh vertices(const std::string& text); const Texture* text_texture(); static const std::string& font_path(); + static float text_width(const std::string& text); private: FT_Library m_ft; diff --git a/include/Cubed/ui/chat_box.hpp b/include/Cubed/ui/chat_box.hpp index 0ee7416..cbb47fb 100644 --- a/include/Cubed/ui/chat_box.hpp +++ b/include/Cubed/ui/chat_box.hpp @@ -51,5 +51,6 @@ private: void on_render(Renderer& renderer) override; bool handle_text_input_event(const TextInputEvent& e) override; bool handle_key_event(const KeyEvent& e) override; + std::vector wrap_message(const std::string& text) const; }; } // namespace Cubed \ No newline at end of file diff --git a/src/tools/font.cpp b/src/tools/font.cpp index fd986a2..1c53c18 100644 --- a/src/tools/font.cpp +++ b/src/tools/font.cpp @@ -154,6 +154,28 @@ TextMesh Font::vertices(const std::string& text) { return {std::move(vertices), max_x - min_x, max_y - min_y, 0, 0}; } +float Font::text_width(const std::string& text) { + auto& f = Font::get(); + + hb_buffer_t* buffer = hb_buffer_create(); + + hb_buffer_add_utf8(buffer, text.c_str(), text.size(), 0, text.size()); + hb_buffer_guess_segment_properties(buffer); + hb_shape(f.m_hb_font, buffer, nullptr, 0); + + unsigned int count = 0; + auto* positions = hb_buffer_get_glyph_positions(buffer, &count); + + hb_position_t advance = 0; + for (unsigned int i = 0; i < count; ++i) { + advance += positions[i].x_advance; + } + + hb_buffer_destroy(buffer); + + return static_cast(advance) / 64.0f; +} + const Texture* Font::text_texture() { return m_text_texture.get(); } const std::string& Font::font_path() { return m_font_path; } diff --git a/src/ui/chat_box.cpp b/src/ui/chat_box.cpp index 3ccf6f6..5200c11 100644 --- a/src/ui/chat_box.cpp +++ b/src/ui/chat_box.cpp @@ -1,7 +1,9 @@ #include "Cubed/ui/chat_box.hpp" -#include "Cubed/tools/text_tools.hpp" +#include "Cubed/tools/font.hpp" #include "Cubed/tools/time_tools.hpp" + +#include namespace Cubed { ChatBox::ChatBox(Widget* parent) : Widget(parent) {} @@ -12,7 +14,7 @@ void ChatBox::add_message(ChatMessage& message) { std::string str = std::format("<{}>{}", message.player, message.text); - auto split_str = split_utf8(str, 20); + auto split_str = wrap_message(str); for (auto it = split_str.begin(); it != split_str.end(); ++it) { auto lable = std::make_unique