diff --git a/src/renderer/backend/dx/dx_window.cpp b/src/renderer/backend/dx/dx_window.cpp index 5f4216b..321b35c 100644 --- a/src/renderer/backend/dx/dx_window.cpp +++ b/src/renderer/backend/dx/dx_window.cpp @@ -113,9 +113,12 @@ void dx_window::begin_frame() { // if (test_texture) context.draw_texture({ 0.f, 0.f }, test_texture->size().cast(), test_texture); // context.draw_string({0, 0}, U"你好,世界!全是水群大师\n测试换行\n测试Unicode: 😀\nТест по русскому языку\nテスト日本語", 32, {0, 0, 0, 1}); - context.draw_string({0, 100}, U"你好,世界!\nТест по русскому языку\nテスト", 32, {0, 0, 0, 1}); + float font_height = 64; + context.draw_string({0, 100}, U"你好,世界!\nТест по русскому языку\nテスト", font_height, {0, 0, 0, 1}); context.draw_rectangle({ 0, 100 }, { 2048, 1 }, { 1, 0, 1, 1 }); - context.draw_rectangle({ 0, 132 }, { 2048, 1 }, { 1, 0, 1, 1 }); + context.draw_rectangle({ 0, 100 + font_height }, { 2048, 1 }, { 1, 0, 1, 1 }); + context.draw_rectangle({ 0, 100 + font_height * 2 }, { 2048, 1 }, { 1, 0, 1, 1 }); + context.draw_rectangle({ 0, 100 + font_height * 3 }, { 2048, 1 }, { 1, 0, 1, 1 }); context.flush(); diff --git a/src/renderer/core/renderer/renderer_context.cpp b/src/renderer/core/renderer/renderer_context.cpp index e85d77e..44baff8 100644 --- a/src/renderer/core/renderer/renderer_context.cpp +++ b/src/renderer/core/renderer/renderer_context.cpp @@ -8,7 +8,7 @@ aorii_text* text = nullptr; void renderer_context::init() { text = new aorii_text(); // D:\Projects\aorii\JetBrainsMono-Regular.ttf - text->initialize(LR"(C:\Windows\Fonts\simhei.ttf)"); + text->initialize(LR"(HarmonyOS_Sans_SC_Regular.ttf)"); text->add_font(LR"(C:\Windows\Fonts\seguiemj.ttf)"); // text->precache_common_characters(); } diff --git a/src/renderer/core/renderer/renderer_text.cpp b/src/renderer/core/renderer/renderer_text.cpp index d13a64a..c476273 100644 --- a/src/renderer/core/renderer/renderer_text.cpp +++ b/src/renderer/core/renderer/renderer_text.cpp @@ -184,7 +184,7 @@ std::vector aorii_text::measure_text(const std::u32string& text, fl const int32_t ascent = primary_font.ascent; const int32_t descent = primary_font.descent; const float line_gap = primary_font.line_gap * scale; - const int32_t line_height = height; + const float line_height = height; const float space_width = primary_font.space_width * scale; const float tab_width = primary_font.tab_width * scale; @@ -209,29 +209,39 @@ std::vector aorii_text::measure_text(const std::u32string& text, fl lines.emplace_back(text_copy); for (auto& data: lines) { - int32_t max_top = 0; int32_t min_top = 0; - int32_t max_bottom = 0; int32_t min_bottom = 0; + int32_t max_top = 0; + int32_t max_bottom = 0; for (const auto& ch: data.text) { const auto item = get_atlas_item(ch); if (!item) continue; - max_top = std::max(max_top, item->top); min_top = std::min(min_top, item->top); - max_bottom = std::max(max_bottom, item->bottom); min_bottom = std::min(min_bottom, item->bottom); + max_top = std::max(max_top, item->top); + max_bottom = std::max(max_bottom, item->bottom); } - data.max_top = max_top; data.min_top = min_top; - data.max_bottom = max_bottom; data.min_bottom = min_bottom; + data.max_top = max_top; + data.max_bottom = max_bottom; + // 如果min_top小于0, 则将max_bottom减去min_top + // if (min_top < 0) { + // data.max_bottom -= min_top; + // data.min_bottom -= min_top; + // data.max_top -= min_top; + // data.min_top = 0; + // } } std::vector result; Eigen::Vector2f pos{0, 0}; for (const auto& line : lines) { + // 计算这一行顶部和底部的最大和最小值,然后进行垂直居中 + const float top_offset = (line_height - (line.max_bottom - line.min_top) * scale) / 2; + for (const auto& ch : line.text) { if (ch == U' ') { pos.x() += space_width; @@ -253,14 +263,17 @@ std::vector aorii_text::measure_text(const std::u32string& text, fl if (item_height > line_height) { mch.size_scale = line_height / item_height * scale; } - // 注意字符坐标系的原点在左下角 - // 如果字符的顶部高于行的顶部,则将其对齐到min_top - if (item->top < 0) { - mch.offset.y() += (line.min_top - item->top) * mch.size_scale; - } + // 将字符底部对齐到行底部 + const float bottom_offset = item->bottom - line.max_bottom; + mch.offset.y() -= bottom_offset * mch.size_scale; + // mch.offset.y() += line_height; - pos.x() += (item->right - item->left) * mch.size_scale; + mch.offset.y() += top_offset; + // mch.offset.x() += item->left * mch.size_scale; + + pos.x() += item->x_advance * mch.size_scale; + // pos.x() -= item->left * mch.size_scale; } result.push_back(mch); } @@ -268,7 +281,7 @@ std::vector aorii_text::measure_text(const std::u32string& text, fl pos.x() = 0; pos.y() += line_height; pos.y() += line_gap; - pos.y() -= scale_padding * 2; + // pos.y() -= scale_padding * 2; } return result; } @@ -344,7 +357,11 @@ ch_atlas_item const* aorii_text::cache_ch_to_atlas(char32_t ch) { stbtt_GetGlyphHMetrics(font, glyph_index, &advance_width, &left_side_bearing); int ch_x0, ch_y0, ch_x1, ch_y1; stbtt_GetGlyphBox(font, glyph_index, &ch_x0, &ch_y0, &ch_x1, &ch_y1); - spdlog::info("left: {}, right: {}, top: {}, bottom: {}", ch_x0, ch_x1, ch_y0, ch_y1); + + int width_log = ch_x1 - ch_x0; + int height_log = ch_y1 - ch_y0; + spdlog::info("left: {}, right: {}, top: {}, bottom: {}, width: {}, height: {}, x_advance: {}, left_side_bearing: {}", + ch_x0, ch_x1, ch_y0, ch_y1, width_log, height_log, advance_width, left_side_bearing); // 将x_offset和y_offset转换到字体空间 x_offset = x_offset / scale; diff --git a/src/renderer/core/renderer/renderer_text.h b/src/renderer/core/renderer/renderer_text.h index 783163f..a00ee40 100644 --- a/src/renderer/core/renderer/renderer_text.h +++ b/src/renderer/core/renderer/renderer_text.h @@ -7,24 +7,24 @@ class renderer_texture_array; struct stbtt_fontinfo; struct ch_atlas_item { - float tex_u; // U position in atlas - float tex_v; // V position in atlas - uint8_t tex_z; // Z position in texture array - float u_size; // Texture width - float v_size; // Texture height + float tex_u; // 图集中的U位置 + float tex_v; // 图集中的V位置 + uint8_t tex_z; // 图集索引 + float u_size; // U方向尺寸 + float v_size; // V方向尺寸 - int32_t x_offset; // X offset from baseline - int32_t y_offset; // Y offset from baseline + int32_t x_offset; // SDF纹理的X偏移量 + int32_t y_offset; // SDF纹理的Y偏移量 - int32_t left; - int32_t right; - int32_t top; - int32_t bottom; - int32_t get_width() const { return right - left; } - int32_t get_height() const { return bottom - top; } + int32_t left; // 字形的左边界 + int32_t right; // 字形的右边界 + int32_t top; // 字形的顶部 + int32_t bottom; // 字形的底部 + [[nodiscard]] int32_t get_width() const { return right - left; } + [[nodiscard]] int32_t get_height() const { return bottom - top; } - int32_t x_advance; - int32_t left_side_bearing; + int32_t x_advance; // 字形的X进度 + int32_t left_side_bearing; // 字形的左侧轴承 }; struct measured_ch { diff --git a/src/renderer/shader/aorii_sdf_text.slang b/src/renderer/shader/aorii_sdf_text.slang index d64f501..37a5eea 100644 --- a/src/renderer/shader/aorii_sdf_text.slang +++ b/src/renderer/shader/aorii_sdf_text.slang @@ -42,9 +42,9 @@ SamplerState sampler_state : register(s0); float4 pixel_main(PSInput input) : SV_Target { float2 uv = input.altas_uv + input.char_size * input.uv; float distance = atlas_texture.Sample(sampler_state, float3(uv, input.altas_index)).r; - return float4(distance, distance, distance, 1.0); + // return float4(distance, distance, distance, 1.0); float range = 0.2; - float alpha = smoothstep(0.4, 0.5, distance); + float alpha = smoothstep(0.3, 0.6, distance); float4 color = input.color; color.a *= alpha;