From c1e16b213ea93bf05cc3d1de23fcda3e9a66f14f Mon Sep 17 00:00:00 2001 From: Nanako <469449812@qq.com> Date: Tue, 24 Dec 2024 09:32:17 +0800 Subject: [PATCH] =?UTF-8?q?TODO:=20=E5=A4=9A=E5=AD=97=E4=BD=93=E5=92=8C?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E7=BC=BA=E5=A4=B1=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/backend/dx/dx_window.cpp | 2 +- .../core/renderer/renderer_context.cpp | 24 ++--- src/renderer/core/renderer/renderer_text.cpp | 89 ++++++++++--------- src/renderer/core/renderer/renderer_text.h | 6 +- 4 files changed, 63 insertions(+), 58 deletions(-) diff --git a/src/renderer/backend/dx/dx_window.cpp b/src/renderer/backend/dx/dx_window.cpp index ed691df..443441f 100644 --- a/src/renderer/backend/dx/dx_window.cpp +++ b/src/renderer/backend/dx/dx_window.cpp @@ -112,7 +112,7 @@ void dx_window::begin_frame() { // context.draw_line( { 600, 600 }, { mouse_x, mouse_y }, { 1, 0, 1, 1 }, thickness); // if (test_texture) context.draw_texture({ 0.f, 0.f }, test_texture->size().cast(), test_texture); - context.draw_string({0, 0}, L"你好,世界!全是水群大师\n测试换行", 32); + context.draw_string({0, 0}, L"你好,世界!全是水群大师\n测试换行\n测试日语: かわいい\n测试俄语: милый", 32); context.flush(); diff --git a/src/renderer/core/renderer/renderer_context.cpp b/src/renderer/core/renderer/renderer_context.cpp index d521aa3..9ff51c8 100644 --- a/src/renderer/core/renderer/renderer_context.cpp +++ b/src/renderer/core/renderer/renderer_context.cpp @@ -54,21 +54,23 @@ void renderer_context::draw_string(const Eigen::Vector2f& in_pos, const std::wst } cursor_x += last_char ? text->get_kerning(last_char, c) : 0; - character_info info{}; - text->get_or_create_character(c, info); + const character_info* info = text->get_or_create_character(c); + if (!info) { + continue; + } // 根据in_height缩放字符大小 - const float y_offset = (info.y_offset + text->get_ascent()) * scale; - const Eigen::Vector2f size { info.width * scale, info.height * scale }; - const Eigen::Vector2f pos { cursor_x + info.x_offset * scale, cursor_y + y_offset }; - cursor_x += info.advance * scale; + const float y_offset = (info->y_offset + text->get_ascent()) * scale; + const Eigen::Vector2f size { info->width * scale, info->height * scale }; + const Eigen::Vector2f pos { cursor_x + info->x_offset * scale, cursor_y + y_offset }; + cursor_x += info->advance * scale; aorii_vertex_param param{}; - param.param_a1 = info.tex_u; - param.param_a2 = info.tex_v; - param.param_a3 = info.tex_z; - param.param_b1 = info.width / (float)text->get_texture_size(); - param.param_b2 = info.height / (float)text->get_texture_size(); + param.param_a1 = info->tex_u; + param.param_a2 = info->tex_v; + param.param_a3 = info->tex_z; + param.param_b1 = info->width / (float)text->get_texture_size(); + param.param_b2 = info->height / (float)text->get_texture_size(); make_rect(pos, size, in_color, 0, param); last_char = c; diff --git a/src/renderer/core/renderer/renderer_text.cpp b/src/renderer/core/renderer/renderer_text.cpp index 88f8c5e..878fa31 100644 --- a/src/renderer/core/renderer/renderer_text.cpp +++ b/src/renderer/core/renderer/renderer_text.cpp @@ -25,13 +25,13 @@ const std::wstring aorii_text::COMMON_PUNCTUATION = const std::wstring aorii_text::COMMON_NUMBERS = L"0123456789"; -aorii_text::aorii_text(const uint32_t in_texture_size) : font(nullptr), texture_array(nullptr), +aorii_text::aorii_text(const uint32_t in_texture_size) : fonts(nullptr), texture_array(nullptr), texture_size(in_texture_size), current_x(0), current_y(0), current_texture_index(0), scale(0) { } aorii_text::~aorii_text() { - delete font; + delete fonts; } bool aorii_text::init_freetype() { @@ -44,7 +44,7 @@ void aorii_text::destroy_freetype() { bool aorii_text::initialize(const wchar_t* in_font_path, const float in_font_pixel_size) { const std::string font_path_a(in_font_path, in_font_path + wcslen(in_font_path)); - font = new stbtt_fontinfo(); + auto font = new stbtt_fontinfo(); font_pixel_size = in_font_pixel_size; // 加载字体文件 @@ -67,7 +67,6 @@ bool aorii_text::initialize(const wchar_t* in_font_path, const float in_font_pix spdlog::error("Failed to initialize font"); free(font_buffer); delete font; - font = nullptr; return false; } @@ -78,8 +77,9 @@ bool aorii_text::initialize(const wchar_t* in_font_path, const float in_font_pix ascent *= scale; descent *= scale; line_gap *= scale; - spdlog::info("Font vertical metrics:\n 上升距离: {}, 下降距离: {}, 行间距: {}", ascent, descent, line_gap); + spdlog::info("Font vertical metrics: 上升距离: {}, 下降距离: {}, 行间距: {}", ascent, descent, line_gap); + fonts.push_back(font); // Create initial texture atlas return create_new_texture_atlas(); } @@ -96,26 +96,16 @@ bool aorii_text::create_new_texture_atlas() { return texture_array != nullptr; } -bool aorii_text::get_or_create_character(const wchar_t ch, character_info& out_info) { +character_info* aorii_text::get_or_create_character(const wchar_t ch) { if (const auto it = character_map.find(ch); it != character_map.end()) { - out_info = it->second; - return true; + return &it->second; } - - // 加载目标字符(以 'A' 为例) - int glyph_index = stbtt_FindGlyphIndex(font, ch); - if (glyph_index == 0) { - printf("Failed to find glyph for character\n"); - return false; - } - // Try to add to current atlas - out_info = add_character_to_atlas(glyph_index, ch); - return true; + return add_character_to_atlas(ch); } bool aorii_text::precache_characters(const std::wstring& characters) { - if (!font) { + if (!fonts.size()) { spdlog::error("Font not initialized"); return false; } @@ -138,14 +128,8 @@ bool aorii_text::precache_characters(const std::wstring& characters) { continue; } - // 加载目标字符(以 'A' 为例) - int glyph_index = stbtt_FindGlyphIndex(font, ch); - if (glyph_index == 0) { - continue; - } - // 生成SDF数据 - add_character_to_atlas(glyph_index, ch); + add_character_to_atlas(ch); } return success; @@ -166,31 +150,49 @@ bool aorii_text::precache_common_characters() { return precache_characters(all_common_chars); } -uint32_t aorii_text::get_font_char_count() const { return font->numGlyphs; } +uint32_t aorii_text::get_font_char_count() const { + uint32_t char_count = 0; + for (auto& font : fonts) { + char_count += font->numGlyphs; + } + return char_count; +} -character_info& aorii_text::add_character_to_atlas(int32_t glyph_index, const wchar_t ch) { +character_info* aorii_text::add_character_to_atlas(const wchar_t ch) { // 获取SDF尺寸和位图 int32_t width, height, x_offset, y_offset; constexpr int padding = 8; constexpr uint8_t on_edge_value = 128; constexpr float pixel_dist_scale = 16.f; - auto* sdf_bitmap = stbtt_GetGlyphSDF( - font, - scale, - glyph_index, - padding, - on_edge_value, - pixel_dist_scale, - &width, &height, - &x_offset, &y_offset - ); + uint8_t* sdf_bitmap = nullptr; + const stbtt_fontinfo* font_info = nullptr; + for (const auto f: fonts) { + const uint32_t glyph_index = stbtt_FindGlyphIndex(f, ch); + if (glyph_index == 0) + continue; + sdf_bitmap = stbtt_GetGlyphSDF( + f, + scale, + glyph_index, + padding, + on_edge_value, + pixel_dist_scale, + &width, &height, + &x_offset, &y_offset + ); + if (sdf_bitmap) { + font_info = f; + break; + } + } if (!sdf_bitmap) { - throw std::runtime_error("Failed to generate SDF for glyph"); + spdlog::error("Failed to generate SDF for glyph {}", ch); + return nullptr; } ON_SCOPE_EXIT { - stbtt_FreeSDF(sdf_bitmap, font->userdata); + stbtt_FreeSDF(sdf_bitmap, font_info->userdata); }; // 检查当前行是否有足够空间 @@ -204,7 +206,8 @@ character_info& aorii_text::add_character_to_atlas(int32_t glyph_index, const wc if (current_y + height > texture_size) { current_texture_index++; if (current_texture_index >= texture_array->get_count()) { - throw std::runtime_error("Texture array capacity exceeded"); + spdlog::error("Texture array capacity exceeded"); + return nullptr; } current_x = 0; current_y = 0; @@ -220,7 +223,7 @@ character_info& aorii_text::add_character_to_atlas(int32_t glyph_index, const wc // 获取字形度量信息 int advance_width, left_side_bearing; - stbtt_GetGlyphHMetrics(font, glyph_index, &advance_width, &left_side_bearing); + stbtt_GetGlyphHMetrics(font_info, glyph_index, &advance_width, &left_side_bearing); // 创建并存储字符信息 character_info info; @@ -237,6 +240,6 @@ character_info& aorii_text::add_character_to_atlas(int32_t glyph_index, const wc current_x += width; next_row_y = std::max(next_row_y, current_y + height); - return character_map[ch] = info; + return &(character_map[ch] = info); } diff --git a/src/renderer/core/renderer/renderer_text.h b/src/renderer/core/renderer/renderer_text.h index 94510e6..f933b5c 100644 --- a/src/renderer/core/renderer/renderer_text.h +++ b/src/renderer/core/renderer/renderer_text.h @@ -28,7 +28,7 @@ public: static void destroy_freetype(); bool initialize(const wchar_t* in_font_path, float in_font_pixel_size); - bool get_or_create_character(wchar_t ch, character_info& out_info); + character_info* get_or_create_character(wchar_t ch); // 上升距离 [[nodiscard]] int32_t get_ascent() const { return ascent; } // 下降距离 @@ -57,8 +57,8 @@ public: float get_kerning(wchar_t ch1, wchar_t ch2) const; private: bool create_new_texture_atlas(); - character_info& add_character_to_atlas(int32_t glyph_index, const wchar_t ch); - stbtt_fontinfo* font; + character_info* add_character_to_atlas(wchar_t ch); + std::vector fonts; renderer_texture_array* texture_array; const uint32_t texture_size;