优化文本布局
This commit is contained in:
parent
12b6d058df
commit
cc37be615c
@ -60,27 +60,27 @@ int main(int argc, char* argv[]) {
|
||||
ss << "license: " << license << "\n";
|
||||
|
||||
// const char*转换为std::u32string
|
||||
const auto& config_info_str = utf8::utf8to32(ss.str());
|
||||
// const auto& config_info_str = utf8::utf8to32(ss.str());
|
||||
// text_block->set_text(U"Hello, World! 你好,世界!\n换行测试1111,测试测试测试测试,测试测试😀🐵🙏 😃🐵🙏");
|
||||
|
||||
const auto& window = mwindow::create({ 800, 600 }, L"Hello, World!");
|
||||
window->set_content(
|
||||
mnew(mv_box)
|
||||
[
|
||||
mslot(mv_box)
|
||||
.horizontal_alignment(horizontal_alignment_t::left)
|
||||
+ mnew(mbutton)
|
||||
[
|
||||
mslot(mbutton)
|
||||
.margin({ 10 })
|
||||
.visibility(visibility_t::visible)
|
||||
[
|
||||
mnew(mtext_block,
|
||||
.text(config_info_str)
|
||||
.font_size(24)
|
||||
)
|
||||
]
|
||||
],
|
||||
// mslot(mv_box)
|
||||
// .horizontal_alignment(horizontal_alignment_t::left)
|
||||
// + mnew(mbutton)
|
||||
// [
|
||||
// mslot(mbutton)
|
||||
// .margin({ 10 })
|
||||
// .visibility(visibility_t::visible)
|
||||
// [
|
||||
// mnew(mtext_block,
|
||||
// .text(config_info_str)
|
||||
// .font_size(24)
|
||||
// )
|
||||
// ]
|
||||
// ],
|
||||
|
||||
mslot(mv_box)
|
||||
.horizontal_alignment(horizontal_alignment_t::right)
|
||||
@ -91,7 +91,8 @@ int main(int argc, char* argv[]) {
|
||||
.visibility(visibility_t::visible)
|
||||
[
|
||||
mnew(mtext_block,
|
||||
.text(U"Hello, World!")
|
||||
.text(U"Hello, World! 你好,世界!\n换行测试1111,测试测试测试测试,测试测试😀🐵🙏 😃🐵🙏")
|
||||
// .text(U"😀🐵🙏😀🐵🙏")
|
||||
.font_size(24)
|
||||
)
|
||||
]
|
||||
|
@ -7,14 +7,6 @@ add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC mirage_core sokol mirage_image)
|
||||
|
||||
option(MIRAGE_SVG_EMOJI "Use svg emoji" ON)
|
||||
if (MIRAGE_SVG_EMOJI)
|
||||
find_package(nanosvg REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC NanoSVG::nanosvg NanoSVG::nanosvgrast ZLIB::ZLIB)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC HAS_NANOSVG)
|
||||
endif ()
|
||||
|
||||
# 设置图像加载器
|
||||
set(MIRAGE_IMAGE_LOAD_BACKEND "STB_IMAGE" CACHE STRING "选择图像加载器")
|
||||
set_property(CACHE MIRAGE_IMAGE_LOAD_BACKEND PROPERTY STRINGS "STB_IMAGE" "CUSTOM")
|
||||
|
@ -1,80 +1,113 @@
|
||||
#include "font_system.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "emoji_detector.h"
|
||||
|
||||
void font_manager::destroy() {
|
||||
fonts_.clear();
|
||||
emoji_font_ids_.clear();
|
||||
atlas_manager_.clear();
|
||||
primary_font_id_ = -1;
|
||||
next_font_id_ = 0;
|
||||
destroy_font_system();
|
||||
fonts_.clear();
|
||||
emoji_font_ids_.clear();
|
||||
atlas_manager_.clear();
|
||||
primary_font_id_ = -1;
|
||||
next_font_id_ = 0;
|
||||
destroy_font_system();
|
||||
}
|
||||
|
||||
void font_manager::load_default_font() {
|
||||
#if MIRAGE_PLATFORM_WINDOWS
|
||||
add_font(L"C:/Windows/Fonts/msyh.ttc");
|
||||
add_font(L"C:/Windows/Fonts/seguiemj.ttf");
|
||||
add_font(L"C:/Windows/Fonts/msyh.ttc");
|
||||
add_font(L"C:/Windows/Fonts/seguiemj.ttf");
|
||||
#else
|
||||
static_assert(false, "暂时不支持当前平台的默认字体加载");
|
||||
#endif
|
||||
}
|
||||
|
||||
int font_manager::add_font(const std::filesystem::path& in_font_path, const std::string& in_font_type) {
|
||||
auto font = create_font_face(in_font_path);
|
||||
if (!font) {
|
||||
return -1;
|
||||
}
|
||||
const auto font = create_font_face(in_font_path);
|
||||
if (!font) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int font_id = next_font_id_++;
|
||||
fonts_[font_id] = font;
|
||||
const auto font_id = next_font_id_++;
|
||||
fonts_[font_id] = font;
|
||||
|
||||
// 如果支持彩色表情或明确指定为表情字体,添加到表情字体列表
|
||||
if (font->supports_color_emoji() || in_font_type == "emoji") {
|
||||
emoji_font_ids_.push_back(font_id);
|
||||
}
|
||||
// 如果支持彩色表情或明确指定为表情字体,添加到表情字体列表
|
||||
if (font->supports_color_emoji() || in_font_type == "emoji") {
|
||||
emoji_font_ids_.push_back(font);
|
||||
}
|
||||
|
||||
// 如果是第一个添加的字体,自动设为主字体
|
||||
if (primary_font_id_ == -1) {
|
||||
primary_font_id_ = font_id;
|
||||
}
|
||||
// 如果是第一个添加的字体,自动设为主字体
|
||||
if (primary_font_id_ == -1) {
|
||||
primary_font_id_ = font_id;
|
||||
}
|
||||
|
||||
return font_id;
|
||||
return font_id;
|
||||
}
|
||||
|
||||
std::shared_ptr<font_face_interface> font_manager::get_font_for_code_point(
|
||||
std::shared_ptr<font_face_interface> in_custom_primary_font, uint32_t in_code_point, uint32_t* out_glyph_index) {
|
||||
if (in_custom_primary_font) {
|
||||
uint32_t glyph_id = in_custom_primary_font->find_glyph_index(in_code_point);
|
||||
if (glyph_id > 0) {
|
||||
if (out_glyph_index)
|
||||
*out_glyph_index = glyph_id;
|
||||
return in_custom_primary_font;
|
||||
}
|
||||
}
|
||||
const std::shared_ptr<font_face_interface>& in_custom_primary_font, const uint32_t in_code_point,
|
||||
uint32_t* out_glyph_index) {
|
||||
// **辅助 Lambda:检查字体并更新字形索引**
|
||||
auto check_font = [&](const std::shared_ptr<font_face_interface>& font) -> std::shared_ptr<font_face_interface> {
|
||||
if (!font)
|
||||
return nullptr; // 跳过空指针
|
||||
|
||||
// 对表情符号使用表情符号字体
|
||||
if (emoji_detector::is_emoji(in_code_point)) {
|
||||
for (int emoji_id : emoji_font_ids_) {
|
||||
auto emoji_font = fonts_[emoji_id];
|
||||
if (emoji_font && emoji_font->has_glyph(in_code_point)) {
|
||||
return emoji_font;
|
||||
}
|
||||
}
|
||||
}
|
||||
// **调用字体接口查找字形索引 (Assuming 0 means 'not found')**
|
||||
const uint32_t glyph_id = font->find_glyph_index(in_code_point);
|
||||
if (glyph_id > 0) {
|
||||
// **如果找到字形,设置输出参数并返回字体**
|
||||
if (out_glyph_index) {
|
||||
*out_glyph_index = glyph_id;
|
||||
}
|
||||
return font; // 找到字形
|
||||
}
|
||||
return nullptr; // 在此字体中未找到字形
|
||||
};
|
||||
|
||||
// 尝试所有其他字体
|
||||
for (const auto& [id, font] : fonts_) {
|
||||
uint32_t glyph_id = font->find_glyph_index(in_code_point);
|
||||
if (id != primary_font_id_ && glyph_id > 0) {
|
||||
if (out_glyph_index)
|
||||
*out_glyph_index = glyph_id;
|
||||
return font;
|
||||
}
|
||||
}
|
||||
// **1. 尝试自定义主字体 (如果提供了)**
|
||||
if (auto found_font = check_font(in_custom_primary_font)) {
|
||||
return found_font; // 在主字体中找到,直接返回
|
||||
}
|
||||
|
||||
// 回退到主字体
|
||||
return in_custom_primary_font;
|
||||
// 确定字符类型
|
||||
const bool is_emoji = emoji_detector::is_emoji(in_code_point);
|
||||
|
||||
// **2. 定义字体过滤器**
|
||||
// 此过滤器排除了空指针字体和已检查过的主字体。
|
||||
// 注意: 更复杂的过滤器可以基于 is_emoji 和字体元数据 (例如 is_emoji_font())
|
||||
// 来优先选择特定类型的字体(例如,为表情符号优先选择表情字体)。
|
||||
auto font_filter = [&](const std::shared_ptr<font_face_interface>& font) {
|
||||
// **确保字体有效且不是我们已经检查过的主字体**
|
||||
if (is_emoji) {
|
||||
return std::ranges::contains(emoji_font_ids_, font);
|
||||
}
|
||||
return font != nullptr && font != in_custom_primary_font;
|
||||
};
|
||||
|
||||
// **3. 遍历字体管理器中所有其他适用的字体**
|
||||
for (const auto& font : std::views::values(fonts_) | std::views::filter(font_filter)) {
|
||||
// **检查当前遍历到的字体**
|
||||
if (auto found_font = check_font(font)) {
|
||||
return found_font; // 在其他受管字体中找到,返回
|
||||
}
|
||||
}
|
||||
|
||||
// **4. 最终回退逻辑**
|
||||
// 如果代码执行到这里,表示在主字体(如果提供)和所有其他过滤后的字体中都未找到该字形。
|
||||
// (可选) 在这里可以尝试一个全局默认回退字体:
|
||||
// if (m_global_fallback_font) {
|
||||
// if (auto found_font = check_font(m_global_fallback_font)) {
|
||||
// return found_font;
|
||||
// }
|
||||
// }
|
||||
|
||||
// **未能找到任何包含该字形的字体**
|
||||
// **将输出字形索引设置为 0 (表示未找到)**
|
||||
if (out_glyph_index) {
|
||||
*out_glyph_index = 0;
|
||||
}
|
||||
// **返回 nullptr,表示没有找到合适的字体**
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
text_layout_t font_manager::layout_text(
|
||||
@ -82,8 +115,7 @@ text_layout_t font_manager::layout_text(
|
||||
const std::shared_ptr<font_face_interface>& in_font,
|
||||
float font_size,
|
||||
float max_width,
|
||||
float line_spacing)
|
||||
{
|
||||
float line_spacing) {
|
||||
text_layout_t layout;
|
||||
|
||||
// 使用指定字体或主字体
|
||||
@ -92,18 +124,18 @@ text_layout_t font_manager::layout_text(
|
||||
primary_font->set_font_size(font_size);
|
||||
|
||||
// 初始化布局变量
|
||||
float cursor_x = 0.0f; // 当前光标X位置
|
||||
float cursor_y = 0.0f; // 当前光标Y位置
|
||||
float width = 0.0f; // 总布局宽度
|
||||
float height = 0.0f; // 总布局高度
|
||||
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; // 行宽度
|
||||
float height = 0.0f; // 行总高度
|
||||
float ascent = 0.0f; // 最大上升距离
|
||||
float descent = 0.0f; // 最大下降距离
|
||||
float line_width = 0.0f; // 行宽度
|
||||
bool has_content = false; // 标记行是否有内容
|
||||
};
|
||||
|
||||
@ -127,6 +159,13 @@ text_layout_t font_manager::layout_text(
|
||||
}
|
||||
};
|
||||
|
||||
// 设置字体大小
|
||||
for (const auto& font : fonts_ | std::views::values) {
|
||||
font->set_font_size(font_size);
|
||||
}
|
||||
|
||||
std::map<std::shared_ptr<font_face_interface>, font_v_metrics_t> font_metrics;
|
||||
|
||||
/**
|
||||
* @brief 处理单个字符的布局
|
||||
*
|
||||
@ -143,18 +182,19 @@ text_layout_t font_manager::layout_text(
|
||||
const bool is_emoji = emoji_detector::is_emoji(c);
|
||||
|
||||
// 查找能够渲染此字符的字体
|
||||
uint32_t glyph_index = 0;
|
||||
uint32_t glyph_index = 0;
|
||||
const auto& using_font = get_font_for_code_point(primary_font, c, &glyph_index);
|
||||
|
||||
if (glyph_index == 0) {
|
||||
return; // 如果没有找到支持的字体,跳过该字符
|
||||
return; // 如果没有找到支持的字体,跳过该字符
|
||||
}
|
||||
|
||||
// 设置当前字体大小
|
||||
using_font->set_font_size(font_size);
|
||||
if (!font_metrics.contains(using_font)) {
|
||||
font_metrics[using_font] = using_font->get_metrics();
|
||||
}
|
||||
|
||||
// 获取当前字体的度量信息
|
||||
const auto& current_metrics = using_font->get_metrics();
|
||||
const auto& current_metrics = font_metrics[using_font];
|
||||
|
||||
// 获取字形度量信息(形状、尺寸、间距等)
|
||||
const auto& glyph_metrics = using_font->shape_glyph(glyph_index);
|
||||
@ -163,7 +203,7 @@ text_layout_t font_manager::layout_text(
|
||||
const auto& region = get_or_create_glyph_by_index(glyph_metrics.glyph_index, using_font, font_size, is_emoji);
|
||||
|
||||
if (!region) {
|
||||
return; // 如果无法获取或创建字形区域,跳过该字符
|
||||
return; // 如果无法获取或创建字形区域,跳过该字符
|
||||
}
|
||||
|
||||
// 检查是否需要自动换行
|
||||
@ -183,7 +223,8 @@ text_layout_t font_manager::layout_text(
|
||||
|
||||
// 计算基线位置 - 基于当前行的上升距离
|
||||
const auto baseline = cursor_y + current_line.ascent;
|
||||
const auto size_y_diff = glyph_metrics.rect.size().y() - region->rect.size().y(); // 计算Y轴差异(字形位图高度与区域高度)
|
||||
// 计算Y轴差异(字形位图高度与区域高度)
|
||||
const auto size_y_diff = glyph_metrics.rect.size().y() - static_cast<float>(region->rect.size().y());
|
||||
|
||||
// 计算字形绘制坐标
|
||||
auto x = cursor_x + glyph_metrics.offset.x();
|
||||
@ -237,19 +278,18 @@ std::optional<atlas_region_t> font_manager::get_or_create_glyph_by_index(
|
||||
int32_t in_glyph_id,
|
||||
const std::shared_ptr<font_face_interface>& in_font,
|
||||
float in_font_size,
|
||||
bool is_emoji)
|
||||
{
|
||||
bool is_emoji) {
|
||||
// 验证字体有效性
|
||||
if (!in_font) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return atlas_manager_.get_or_create_glyph(in_glyph_id, in_font, in_font_size, is_emoji);
|
||||
return atlas_manager_.get_or_create_glyph(in_glyph_id, in_font, in_font_size, is_emoji);
|
||||
}
|
||||
|
||||
font_manager::font_manager() {
|
||||
// 初始化字体系统
|
||||
if (!init_font_system()) {
|
||||
throw std::runtime_error("无法初始化字体系统");
|
||||
}
|
||||
// 初始化字体系统
|
||||
if (!init_font_system()) {
|
||||
throw std::runtime_error("无法初始化字体系统");
|
||||
}
|
||||
}
|
||||
|
@ -21,73 +21,77 @@
|
||||
*/
|
||||
class font_manager {
|
||||
public:
|
||||
/**
|
||||
* @brief 获取单例实例
|
||||
*
|
||||
* @return font_manager& 字体管理器的单例引用
|
||||
*/
|
||||
static font_manager& instance() {
|
||||
static font_manager instance;
|
||||
return instance;
|
||||
}
|
||||
/**
|
||||
* @brief 获取单例实例
|
||||
*
|
||||
* @return font_manager& 字体管理器的单例引用
|
||||
*/
|
||||
static font_manager& instance() {
|
||||
static font_manager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 销毁所有资源
|
||||
*
|
||||
* 清理所有字体和图集资源,重置字体管理器状态。
|
||||
*/
|
||||
void destroy();
|
||||
/**
|
||||
* @brief 销毁所有资源
|
||||
*
|
||||
* 清理所有字体和图集资源,重置字体管理器状态。
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* @brief 加载操作系统默认字体
|
||||
*/
|
||||
void load_default_font();
|
||||
/**
|
||||
* @brief 加载操作系统默认字体
|
||||
*/
|
||||
void load_default_font();
|
||||
|
||||
/**
|
||||
* @brief 添加字体
|
||||
*
|
||||
* 从文件加载字体并添加到字体管理系统中。
|
||||
* 如果字体支持彩色表情符号或指定为表情符号字体,将自动添加到表情符号字体列表。
|
||||
*
|
||||
* @param in_font_path 字体文件路径
|
||||
* @param in_font_type 字体类型(regular, bold, italic, emoji等)
|
||||
* @return 添加成功返回字体ID,失败返回-1
|
||||
*/
|
||||
int add_font(const std::filesystem::path& in_font_path, const std::string& in_font_type = "regular");
|
||||
/**
|
||||
* @brief 添加字体
|
||||
*
|
||||
* 从文件加载字体并添加到字体管理系统中。
|
||||
* 如果字体支持彩色表情符号或指定为表情符号字体,将自动添加到表情符号字体列表。
|
||||
*
|
||||
* @param in_font_path 字体文件路径
|
||||
* @param in_font_type 字体类型(regular, bold, italic, emoji等)
|
||||
* @return 添加成功返回字体ID,失败返回-1
|
||||
*/
|
||||
int add_font(const std::filesystem::path& in_font_path, const std::string& in_font_type = "regular");
|
||||
|
||||
/**
|
||||
* @brief 设置主字体
|
||||
*
|
||||
* @param in_font_id 要设为主字体的字体ID
|
||||
* @return 设置是否成功
|
||||
*/
|
||||
bool set_primary_font(int in_font_id) {
|
||||
if (fonts_.contains(in_font_id)) {
|
||||
primary_font_id_ = in_font_id;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @brief 设置主字体
|
||||
*
|
||||
* @param in_font_id 要设为主字体的字体ID
|
||||
* @return 设置是否成功
|
||||
*/
|
||||
bool set_primary_font(int in_font_id) {
|
||||
if (fonts_.contains(in_font_id)) {
|
||||
primary_font_id_ = in_font_id;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取指定码点的最佳字体
|
||||
*
|
||||
* 实现字体回退机制,按以下顺序尝试查找支持指定码点的字体:
|
||||
* 1. 主字体
|
||||
* 2. 如果是表情符号,尝试表情符号字体
|
||||
* 3. 所有其他字体
|
||||
* 4. 回退到主字体
|
||||
*
|
||||
* @param in_code_point Unicode码点
|
||||
* @return 最适合渲染该码点的字体
|
||||
*/
|
||||
std::shared_ptr<font_face_interface> get_font_for_code_point(uint32_t in_code_point, uint32_t* out_glyph_index = nullptr) {
|
||||
auto primary = get_primary_font();
|
||||
return get_font_for_code_point(primary, in_code_point, out_glyph_index);
|
||||
}
|
||||
std::shared_ptr<font_face_interface> get_font_for_code_point(std::shared_ptr<font_face_interface> in_custom_primary_font, uint32_t in_code_point, uint32_t* out_glyph_index = nullptr);
|
||||
/**
|
||||
* @brief 获取指定码点的最佳字体
|
||||
*
|
||||
* 实现字体回退机制,按以下顺序尝试查找支持指定码点的字体:
|
||||
* 1. 主字体
|
||||
* 2. 如果是表情符号,尝试表情符号字体
|
||||
* 3. 所有其他字体
|
||||
* 4. 回退到主字体
|
||||
*
|
||||
* @param in_code_point Unicode码点
|
||||
* @return 最适合渲染该码点的字体
|
||||
*/
|
||||
std::shared_ptr<font_face_interface> get_font_for_code_point(uint32_t in_code_point,
|
||||
uint32_t* out_glyph_index = nullptr) {
|
||||
auto primary = get_primary_font();
|
||||
return get_font_for_code_point(primary, in_code_point, out_glyph_index);
|
||||
}
|
||||
|
||||
/**
|
||||
std::shared_ptr<font_face_interface> get_font_for_code_point(
|
||||
const std::shared_ptr<font_face_interface>& in_custom_primary_font, uint32_t in_code_point,
|
||||
uint32_t* out_glyph_index = nullptr);
|
||||
|
||||
/**
|
||||
* @brief 获取主字体
|
||||
* @return 主字体
|
||||
*/
|
||||
@ -106,16 +110,16 @@ public:
|
||||
return !emoji_font_ids_.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算文本布局,确定每个字形的位置和大小
|
||||
*
|
||||
* @param text 要布局的Unicode文本
|
||||
* @param in_font 指定的字体(如果为nullptr则使用主字体)
|
||||
* @param font_size 字体大小(像素单位)
|
||||
* @param max_width 文本的最大宽度(用于自动换行,0表示不限制宽度)
|
||||
* @param line_spacing 行间距因子(1.0表示标准行距)
|
||||
* @return text_layout_t 包含所有字形位置和布局信息的结构
|
||||
*/
|
||||
/**
|
||||
* @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,
|
||||
@ -140,28 +144,29 @@ public:
|
||||
float in_font_size,
|
||||
bool is_emoji);
|
||||
|
||||
/**
|
||||
* @brief 获取所有字形图集
|
||||
* @return 字形图集列表的常量引用
|
||||
*/
|
||||
[[nodiscard]] const auto& get_glyph_atlases() const {
|
||||
return atlas_manager_.get_glyph_atlases();
|
||||
}
|
||||
/**
|
||||
* @brief 获取所有字形图集
|
||||
* @return 字形图集列表的常量引用
|
||||
*/
|
||||
[[nodiscard]] const auto& get_glyph_atlases() const {
|
||||
return atlas_manager_.get_glyph_atlases();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取所有表情图集
|
||||
* @return 表情图集列表的常量引用
|
||||
*/
|
||||
[[nodiscard]] const auto& get_emoji_atlases() const {
|
||||
return atlas_manager_.get_emoji_atlases();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取所有表情图集
|
||||
* @return 表情图集列表的常量引用
|
||||
*/
|
||||
[[nodiscard]] const auto& get_emoji_atlases() const {
|
||||
return atlas_manager_.get_emoji_atlases();
|
||||
}
|
||||
private:
|
||||
font_manager();
|
||||
font_manager();
|
||||
|
||||
std::unordered_map<int, std::shared_ptr<font_face_interface>> fonts_; ///< 字体ID到字体对象的映射
|
||||
font_atlas_manager atlas_manager_; ///< 图集管理器
|
||||
std::unordered_map<int32_t, std::shared_ptr<font_face_interface>> fonts_; ///< 字体ID到字体对象的映射
|
||||
font_atlas_manager atlas_manager_; ///< 图集管理器
|
||||
|
||||
std::vector<int> emoji_font_ids_; ///< 表情符号字体ID列表
|
||||
int primary_font_id_ = -1; ///< 主字体ID
|
||||
int next_font_id_ = 0; ///< 下一个可用的字体ID
|
||||
};
|
||||
std::vector<std::shared_ptr<font_face_interface>> emoji_font_ids_; ///< 表情符号字体ID列表
|
||||
int32_t primary_font_id_ = -1; ///< 主字体ID
|
||||
int32_t next_font_id_ = 0; ///< 下一个可用的字体ID
|
||||
};
|
||||
|
@ -12,9 +12,9 @@ class texture2d;
|
||||
* @brief 文本水平对齐方式
|
||||
*/
|
||||
enum class horizontal_text_alignment_t {
|
||||
left, ///< 文本左对齐
|
||||
left, ///< 文本左对齐
|
||||
center, ///< 文本居中对齐
|
||||
right ///< 文本右对齐
|
||||
right ///< 文本右对齐
|
||||
};
|
||||
|
||||
/**
|
||||
@ -32,7 +32,7 @@ enum class vertical_text_alignment_t {
|
||||
* @brief 已定位的字形
|
||||
*/
|
||||
struct positioned_glyph_t {
|
||||
uint32_t code_point = 0; ///< Unicode码点
|
||||
uint32_t code_point = 0; ///< Unicode码点
|
||||
Eigen::Vector2f position; ///< 屏幕位置
|
||||
rect_t<> bounds; ///< 边界矩形
|
||||
float advance = 0.0f; ///< 前进量
|
||||
@ -91,9 +91,9 @@ struct text_line_t {
|
||||
* @brief 段落结构
|
||||
*/
|
||||
struct text_paragraph_t {
|
||||
std::vector<text_line_t> lines; ///< 段落中的行
|
||||
flow_direction_t flow_direction; ///< 文本方向
|
||||
rect_t<> bounds; ///< 段落边界
|
||||
std::vector<text_line_t> lines; ///< 段落中的行
|
||||
flow_direction_t flow_direction; ///< 文本方向
|
||||
rect_t<> bounds; ///< 段落边界
|
||||
};
|
||||
|
||||
/**
|
||||
@ -118,7 +118,7 @@ struct text_style_t {
|
||||
struct text_layout_t {
|
||||
struct glyph_position_t {
|
||||
bool is_emoji; // 是否为表情符号
|
||||
int32_t glyph_index; // 字符码点
|
||||
uint32_t glyph_index; // 字符码点
|
||||
Eigen::Vector2f position; // 屏幕位置
|
||||
Eigen::Vector2f size; // 字形尺寸
|
||||
atlas_region_t region; // 纹理图集区域
|
||||
|
Loading…
x
Reference in New Issue
Block a user