优化行高计算

This commit is contained in:
daiqingshuang 2025-04-02 14:37:41 +08:00
parent e0c0648221
commit da19e27f5b
7 changed files with 35 additions and 55 deletions

View File

@ -12,7 +12,7 @@ int main(int argc, char* argv[]) {
mirage_app::get().init();
auto& manager = font_manager::instance();
manager.add_font(L"C:/Users/46944/AppData/Local/Microsoft/Windows/Fonts/MapleMono-NF-CN-Regular.ttf");
// manager.add_font(L"C:/Users/46944/AppData/Local/Microsoft/Windows/Fonts/MapleMono-NF-CN-Regular.ttf");
manager.add_font(L"C:/Windows/Fonts/msyh.ttc");
// manager.add_font(L"D:/Projects/noto-emoji-2.047/fonts/Noto-COLRv1.ttf");
manager.add_font(L"C:/Windows/Fonts/seguiemj.ttf");
@ -29,7 +29,7 @@ int main(int argc, char* argv[]) {
const auto button2 = std::make_shared<mbutton>();
button2->set_content(text_block2);
const auto& window = mwindow::create({ 1024, 1024 }, L"Hello, World!");
const auto& window = mwindow::create({ 800, 600 }, L"Hello, World!");
window->set_content(
mnew(mh_box)
mslot(mh_box)

View File

@ -53,7 +53,7 @@ font_v_metrics_t freetype_interface::get_metrics() const {
font_v_metrics_t metrics{};
metrics.ascent = face_->ascender / 64.f;
metrics.descent = face_->descender / 64.f;
metrics.line_height = face_->height / 64.f;
metrics.line_height = face_->size->metrics.height / 64.f;
return metrics;
}

View File

@ -76,48 +76,27 @@ text_layout_t font_manager::layout_text(
// 使用指定字体或主字体
const auto& primary_font = in_font ? in_font : get_primary_font();
assert(primary_font && "No valid font available");
primary_font->set_font_size(font_size);
// 初始化布局变量
float cursor_x = 0.0f;
float cursor_y = 0.0f;
float line_max_width = 0.0f;
float cursor_x = 0.f;
float cursor_y = 0.f;
float line_height = 0.f;
const auto& v_metrics = primary_font->get_metrics();
float font_ascent = v_metrics.ascent;
float font_descent = std::abs(v_metrics.descent);
int32_t last_index = 0; // 上一个字形索引,用于字距调整
float line_start_x = 0.0f; // 当前行的起始x坐标
// 当前行的基线位置
float baseline = cursor_y + font_ascent;
// 当前使用的字体,开始时使用主字体
auto using_font = primary_font;
float width = 0.f;
float height = 0.f;
// 完成当前行的布局
auto finish_line = [&]() {
// 根据当前行的最大上升值确定最终基线位置
baseline = cursor_y + font_ascent;
line_max_width = std::max(line_max_width, cursor_x);
const float line_height = v_metrics.line_height + line_spacing;
auto finish_line = [&] {
// 更新总体尺寸
width = std::max(width, cursor_x);
height += line_height + line_spacing;
// 移到下一行
cursor_y += line_height;
cursor_y += line_height + line_spacing;
cursor_x = 0.0f;
line_start_x = 0.0f;
// 重置为下一行的基线计算
font_ascent = v_metrics.ascent;
font_descent = std::abs(v_metrics.descent);
baseline = cursor_y + font_ascent;
line_height = 0.f;
};
layout.ascent = font_ascent;
// 处理每个字符
for (const auto& c : text) {
// 检查是否是换行符
@ -129,6 +108,9 @@ text_layout_t font_manager::layout_text(
// 检查是否是表情符号
const bool is_emoji = emoji_detector::is_emoji(c);
// 当前使用的字体,开始时使用主字体
auto using_font = primary_font;
// 获取字形索引
auto glyph_index = using_font->find_glyph_index(c);
@ -144,6 +126,12 @@ text_layout_t font_manager::layout_text(
}
using_font->set_font_size(font_size);
const auto& v_metrics = primary_font->get_metrics();
line_height = std::max(line_height, v_metrics.line_height);
// 当前行的基线位置
const float baseline = cursor_y + v_metrics.baseline();
// 获取字形度量信息
const auto& glyph_metrics = using_font->shape_glyph(glyph_index);
@ -154,7 +142,7 @@ text_layout_t font_manager::layout_text(
}
// 检查是否需要换行
if (max_width > 0 && cursor_x + glyph_metrics.advance.x() > max_width && cursor_x > line_start_x) { // 确保不是行首字符
if (max_width > 0 && cursor_x + glyph_metrics.advance.x() > max_width) { // 确保不是行首字符
finish_line();
}
@ -172,23 +160,14 @@ text_layout_t font_manager::layout_text(
// 更新光标位置
cursor_x += glyph_metrics.advance.x() + glyph_metrics.rect.left();
// 应用字距调整
if (last_index > 0) {
const float kern_advance = using_font->get_kerning(last_index, glyph_index);
cursor_x += kern_advance;
}
// 记录当前字形索引以便下次计算字距
last_index = glyph_index;
}
finish_line();
// 设置文本布局的总体尺寸
layout.total_size = {
line_max_width,
cursor_y // cursor_y已经包含了所有行的高度
width,
height // cursor_y已经包含了所有行的高度
};
return layout;

View File

@ -126,6 +126,4 @@ struct text_layout_t {
std::vector<glyph_position_t> glyphs; // 所有字形位置
Eigen::Vector2f total_size; // 文本总尺寸
float ascent; // 上升高度
float baseline; // 基线位置
};

View File

@ -16,7 +16,9 @@ struct font_v_metrics_t {
float ascent; // 上升高度
float descent; // 下降高度
float line_height; // 行高
[[nodiscard]] float line_gap() const { return line_height - (ascent - descent); }
[[nodiscard]] float baseline() const { return line_height + descent; }
};
struct glyph_shaped_t {

View File

@ -296,13 +296,14 @@ void render_elements::make_text(const text_layout_t& in_layout, const Eigen::Vec
// make_wireframe(real_pos, size, in_geometry, 1.0f, in_color, in_rotation_radians, in_pivot, in_scale);
}
}
Eigen::Vector2f font_ascent_start = in_pos;
font_ascent_start.y() += in_layout.ascent;
Eigen::Vector2f font_ascent_end = font_ascent_start;
font_ascent_end.x() += in_layout.total_size.x();
// Eigen::Vector2f font_ascent_start = in_pos;
// font_ascent_start.y() += in_layout;
// Eigen::Vector2f font_ascent_end = font_ascent_start;
// font_ascent_end.x() += in_layout.total_size.x();
// 绘制文本的基线
make_line(font_ascent_start, font_ascent_end, in_geometry, 1.0f, in_effect, in_color, in_rotation_radians, in_pivot, in_scale);
// make_line(font_ascent_start, font_ascent_end, in_geometry, 1.0f, in_effect, in_color, in_rotation_radians, in_pivot, in_scale);
// 绘制文本的线框
make_wireframe(in_pos, in_size, in_geometry, 1.0f, in_effect, in_color, in_rotation_radians, in_pivot, in_scale);
}

View File

@ -46,7 +46,7 @@ private:
std::u32string text_;
text_layout_t layout_{};
float font_size_ = 24.0f;
float line_spacing_ = 1.2f;
float line_spacing_ = 1.f;
float max_width_ = 0.0f;
std::shared_ptr<font_face_interface> font_;
};