优化行高计算
This commit is contained in:
parent
e0c0648221
commit
da19e27f5b
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -126,6 +126,4 @@ struct text_layout_t {
|
||||
|
||||
std::vector<glyph_position_t> glyphs; // 所有字形位置
|
||||
Eigen::Vector2f total_size; // 文本总尺寸
|
||||
float ascent; // 上升高度
|
||||
float baseline; // 基线位置
|
||||
};
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user