注释
This commit is contained in:
parent
0c32af832d
commit
c79167eb93
@ -61,9 +61,6 @@ std::shared_ptr<font_face_interface> font_manager::get_font_for_code_point(uint3
|
||||
return primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 布局文本,将Unicode文本转换为可渲染的字形布局
|
||||
*/
|
||||
text_layout_t font_manager::layout_text(
|
||||
const std::u32string& text,
|
||||
const std::shared_ptr<font_face_interface>& in_font,
|
||||
@ -79,25 +76,27 @@ text_layout_t font_manager::layout_text(
|
||||
primary_font->set_font_size(font_size);
|
||||
|
||||
// 初始化布局变量
|
||||
float cursor_x = 0.0f;
|
||||
float cursor_y = 0.0f;
|
||||
float width = 0.0f;
|
||||
float height = 0.0f;
|
||||
uint32_t prev_glyph_id = 0; // 上一个字形索引
|
||||
float cursor_x = 0.0f; // 当前光标X位置
|
||||
float cursor_y = 0.0f; // 当前光标Y位置
|
||||
float width = 0.0f; // 总布局宽度
|
||||
float height = 0.0f; // 总布局高度
|
||||
uint32_t prev_glyph_id = 0; // 上一个字形ID(用于字距调整)
|
||||
|
||||
// 当前行信息
|
||||
struct line_info {
|
||||
float height = 0.0f; // 行总高度
|
||||
float ascent = 0.0f; // 最大上升距离
|
||||
float descent = 0.0f; // 最大下降距离
|
||||
float line_width = 0.0f; // 行宽度
|
||||
bool has_content = false;
|
||||
float height = 0.0f; // 行总高度
|
||||
float ascent = 0.0f; // 最大上升距离
|
||||
float descent = 0.0f; // 最大下降距离
|
||||
float line_width = 0.0f; // 行宽度
|
||||
bool has_content = false; // 标记行是否有内容
|
||||
};
|
||||
|
||||
line_info current_line;
|
||||
|
||||
// 完成当前行的布局
|
||||
auto finish_line = [&] {
|
||||
/**
|
||||
* @brief 完成当前行的布局并准备下一行
|
||||
*/
|
||||
auto finish_line = [&]() {
|
||||
if (current_line.has_content) {
|
||||
// 更新总体尺寸
|
||||
width = std::max(width, current_line.line_width);
|
||||
@ -112,28 +111,30 @@ text_layout_t font_manager::layout_text(
|
||||
}
|
||||
};
|
||||
|
||||
// 处理每个字符
|
||||
for (const auto& c : text) {
|
||||
// 检查是否是换行符
|
||||
/**
|
||||
* @brief 处理单个字符的布局
|
||||
*
|
||||
* @param c 要处理的Unicode字符
|
||||
*/
|
||||
auto process_character = [&](const char32_t c) {
|
||||
// 处理换行符
|
||||
if (c == U'\n') {
|
||||
finish_line();
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否是表情符号
|
||||
const bool is_emoji = emoji_detector::is_emoji(c);
|
||||
|
||||
// 当前使用的字体,开始时使用主字体
|
||||
// 查找能够渲染此字符的字体
|
||||
auto using_font = primary_font;
|
||||
|
||||
// 获取字形索引
|
||||
auto glyph_index = using_font->find_glyph_index(c);
|
||||
|
||||
// 如果当前字体不支持该字符,尝试查找支持该字符的其他字体
|
||||
// 如果主字体不支持该字符,则尝试查找其他字体
|
||||
if (glyph_index == 0) {
|
||||
using_font = get_font_for_code_point(c);
|
||||
if (!using_font) {
|
||||
continue; // 如果没有找到支持的字体,跳过该字符
|
||||
return; // 如果没有找到支持的字体,跳过该字符
|
||||
}
|
||||
|
||||
// 使用新字体重新获取字形索引
|
||||
@ -146,17 +147,21 @@ text_layout_t font_manager::layout_text(
|
||||
// 获取当前字体的度量信息
|
||||
const auto& current_metrics = using_font->get_metrics();
|
||||
|
||||
// 获取字形度量信息
|
||||
// 获取字形度量信息(形状、尺寸、间距等)
|
||||
const auto& glyph_metrics = using_font->shape_glyph(glyph_index);
|
||||
|
||||
// 获取或创建字形在图集中的区域
|
||||
const auto& region = get_or_create_glyph_by_index(glyph_metrics.glyph_index, using_font, font_size, is_emoji);
|
||||
// 获取或创建字形在字形图集中的区域
|
||||
const auto& region = get_or_create_glyph_by_index(
|
||||
glyph_metrics.glyph_index, using_font, font_size, is_emoji);
|
||||
|
||||
if (!region) {
|
||||
continue; // 如果无法在图集中获取或创建字形,跳过该字符
|
||||
return; // 如果无法获取或创建字形区域,跳过该字符
|
||||
}
|
||||
|
||||
// 检查是否需要换行
|
||||
if (max_width > 0 && cursor_x + glyph_metrics.advance.x() > max_width && current_line.has_content) {
|
||||
// 检查是否需要自动换行
|
||||
if (max_width > 0 &&
|
||||
cursor_x + glyph_metrics.advance.x() > max_width &&
|
||||
current_line.has_content) {
|
||||
finish_line();
|
||||
}
|
||||
|
||||
@ -166,38 +171,45 @@ text_layout_t font_manager::layout_text(
|
||||
// 更新当前行的度量信息
|
||||
current_line.ascent = std::max(current_line.ascent, current_metrics.ascent);
|
||||
current_line.descent = std::min(current_line.descent, current_metrics.descent);
|
||||
current_line.height = std::max(current_line.height, current_metrics.line_height);
|
||||
|
||||
// 使用字体的行高
|
||||
current_line.height = std::max(current_line.height, current_metrics.line_height);
|
||||
|
||||
// 计算基线位置 - 使用当前行的上升距离
|
||||
// 计算基线位置 - 基于当前行的上升距离
|
||||
float baseline = cursor_y + current_line.ascent;
|
||||
|
||||
// 计算字形坐标
|
||||
// 计算字形绘制坐标
|
||||
float x = cursor_x + glyph_metrics.hori_bearing.x();
|
||||
float y = baseline + glyph_metrics.hori_bearing.y();
|
||||
|
||||
// 添加字形位置信息到布局
|
||||
auto& glyph_position = layout.glyphs.emplace_back();
|
||||
glyph_position.is_emoji = is_emoji;
|
||||
glyph_position.glyph_index = glyph_index;
|
||||
glyph_position.position = { x, y };
|
||||
glyph_position.size = glyph_metrics.rect.size();
|
||||
glyph_position.region = *region;
|
||||
auto& glyph_position = layout.glyphs.emplace_back();
|
||||
glyph_position.is_emoji = is_emoji;
|
||||
glyph_position.glyph_index = glyph_index;
|
||||
glyph_position.position = { x, y };
|
||||
glyph_position.size = glyph_metrics.rect.size();
|
||||
glyph_position.region = *region;
|
||||
|
||||
// 更新当前行宽度
|
||||
current_line.line_width += glyph_metrics.advance.x();
|
||||
|
||||
current_line.line_width += glyph_metrics.advance.x(); // 更新当前行宽度
|
||||
// 更新光标位置
|
||||
cursor_x += glyph_metrics.advance.x(); // 添加字形间距
|
||||
cursor_x += glyph_metrics.advance.x();
|
||||
|
||||
if (prev_glyph_id != 0) {
|
||||
// 添加字形间距
|
||||
cursor_x += using_font->get_kerning(prev_glyph_id, glyph_index);
|
||||
}
|
||||
// 应用字距调整(kerning)
|
||||
if (prev_glyph_id != 0) {
|
||||
cursor_x += using_font->get_kerning(prev_glyph_id, glyph_index);
|
||||
}
|
||||
|
||||
prev_glyph_id = glyph_index; // 更新上一个字形索引
|
||||
// 更新上一个字形索引
|
||||
prev_glyph_id = glyph_index;
|
||||
};
|
||||
|
||||
// 处理每个字符
|
||||
for (const auto& c : text) {
|
||||
process_character(c);
|
||||
}
|
||||
|
||||
height += current_line.descent; // 最后一行需要减去下降高度
|
||||
// 考虑最后一行的下降部分
|
||||
height -= std::abs(current_line.descent);
|
||||
|
||||
// 处理最后一行
|
||||
finish_line();
|
||||
@ -208,6 +220,7 @@ text_layout_t font_manager::layout_text(
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取或创建字形在图集中的区域
|
||||
*/
|
||||
|
@ -97,18 +97,16 @@ public:
|
||||
return !emoji_font_ids_.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 布局文本
|
||||
*
|
||||
* 将Unicode文本转换为可渲染的字形布局,包括位置计算和换行处理。
|
||||
*
|
||||
* @param text Unicode文本
|
||||
* @param in_font 指定字体,如为空则使用主字体
|
||||
* @param font_size 字体大小
|
||||
* @param max_width 最大宽度,超过此宽度会自动换行,0表示不限制宽度
|
||||
* @param line_spacing 行间距系数
|
||||
* @return 文本布局结果
|
||||
*/
|
||||
/**
|
||||
* @brief 计算文本布局,确定每个字形的位置和大小
|
||||
*
|
||||
* @param text 要布局的Unicode文本
|
||||
* @param in_font 指定的字体(如果为nullptr则使用主字体)
|
||||
* @param font_size 字体大小(像素单位)
|
||||
* @param max_width 文本的最大宽度(用于自动换行,0表示不限制宽度)
|
||||
* @param line_spacing 行间距因子(1.0表示标准行距)
|
||||
* @return text_layout_t 包含所有字形位置和布局信息的结构
|
||||
*/
|
||||
text_layout_t layout_text(
|
||||
const std::u32string& text,
|
||||
const std::shared_ptr<font_face_interface>& in_font,
|
||||
|
Loading…
x
Reference in New Issue
Block a user