diff --git a/src/mirage_config/third_party/tomlplusplus b/src/mirage_config/third_party/tomlplusplus index 2f35c28..fea1d90 160000 --- a/src/mirage_config/third_party/tomlplusplus +++ b/src/mirage_config/third_party/tomlplusplus @@ -1 +1 @@ -Subproject commit 2f35c28a52fd0ada7600273de9aacb66550bcdcb +Subproject commit fea1d905f2d2a8ad830f1985fe879f4fd4601fe5 diff --git a/src/mirage_core/src/misc/lru_cache.h b/src/mirage_core/src/misc/lru_cache.h index 75ac1bf..1ce1c0d 100644 --- a/src/mirage_core/src/misc/lru_cache.h +++ b/src/mirage_core/src/misc/lru_cache.h @@ -1,21 +1,35 @@ #pragma once + #include +#include #include #include #include +#include #include #include -template - requires std::equality_comparable && std::movable +namespace lru_concept { + template + concept Hashable = requires(Key key) { + { std::hash{}(key) } -> std::convertible_to; + }; + + template + concept Movable = std::movable && !std::is_const_v && !std::is_reference_v; +} + +template + requires std::movable class lru_cache { using key_value_pair_t = std::pair; - using list_iterator = typename std::list::iterator; + using list_iterator = typename std::list::iterator; - std::size_t capacity_; - mutable std::list cache_list_; + std::size_t capacity_; + mutable std::list cache_list_; std::unordered_map cache_map_; - mutable std::shared_mutex mutex_; + mutable std::shared_mutex mutex_; + public: explicit lru_cache(std::size_t capacity) : capacity_(capacity) { if (capacity_ == 0) { @@ -23,25 +37,66 @@ public: } } + // 复制构造和赋值 + lru_cache(const lru_cache& other) { + std::shared_lock lock(other.mutex_); + capacity_ = other.capacity_; + cache_list_ = other.cache_list_; + + // 重建 map,因为迭代器在复制后会失效 + for (auto it = cache_list_.begin(); it != cache_list_.end(); ++it) { + cache_map_[it->first] = it; + } + } + + lru_cache& operator=(const lru_cache& other) { + if (this != &other) { + std::unique_lock lock1(mutex_, std::defer_lock); + std::shared_lock lock2(other.mutex_, std::defer_lock); + std::lock(lock1, lock2); + + capacity_ = other.capacity_; + cache_list_ = other.cache_list_; + cache_map_.clear(); + + for (auto it = cache_list_.begin(); it != cache_list_.end(); ++it) { + cache_map_[it->first] = it; + } + } + return *this; + } + + // 移动构造和赋值 + lru_cache(lru_cache&& other) noexcept : capacity_(0) { + std::unique_lock lock(other.mutex_); + capacity_ = std::exchange(other.capacity_, 0); + cache_list_ = std::move(other.cache_list_); + cache_map_ = std::move(other.cache_map_); + } + + lru_cache& operator=(lru_cache&& other) noexcept { + if (this != &other) { + std::unique_lock lock1(mutex_, std::defer_lock); + std::unique_lock lock2(other.mutex_, std::defer_lock); + std::lock(lock1, lock2); + + capacity_ = std::exchange(other.capacity_, 0); + cache_list_ = std::move(other.cache_list_); + cache_map_ = std::move(other.cache_map_); + } + return *this; + } + [[nodiscard]] std::optional get(const Key& key) const { - std::shared_lock lock(mutex_); + // 使用单次加锁,避免 TOCTOU 问题 + std::unique_lock lock(mutex_); auto it = cache_map_.find(key); if (it == cache_map_.end()) { - return std::nullopt; // Key not found + return std::nullopt; } - // 将访问的节点移到链表头部(最近使用) - // 注意: 这里需要修改列表, 所以实际上需要写锁 - - lock.unlock(); - std::unique_lock write_lock(mutex_); - it = cache_map_.find(key); - if (it == cache_map_.end()) { - return std::nullopt; // Key not found - } - - // 将节点移到链表头部 + // 将访问的节点移到链表头部 cache_list_.splice(cache_list_.begin(), cache_list_, it->second); return it->second->second; } @@ -60,15 +115,14 @@ public: // 键不存在,插入新的键值对 if (cache_list_.size() >= capacity_) { - // 缓存已满,请删除最近最少使用的项目 - auto last = cache_list_.end(); - --last; // 获取最后一个元素 + // 缓存已满,删除最近最少使用的项目 + auto last = std::prev(cache_list_.end()); cache_map_.erase(last->first); cache_list_.pop_back(); } - cache_list_.emplace_front(std::pair(key, std::move(value))); - cache_map_[key] = cache_list_.begin(); + cache_list_.emplace_front(key, std::move(value)); + cache_map_.emplace(key, cache_list_.begin()); } // 删除指定key @@ -76,8 +130,8 @@ public: std::unique_lock lock(mutex_); auto it = cache_map_.find(key); - if (it == cache_map_.end()) { - return false; // Key not found + if (it == cache_map_.end()) { // 修复了语法错误 + return false; } cache_list_.erase(it->second); @@ -99,9 +153,7 @@ public: } // 获取缓存容量 - [[nodiscard]] std::size_t capacity() const noexcept { - return capacity_; - } + [[nodiscard]] std::size_t capacity() const noexcept { return capacity_; } // 检查缓存是否为空 [[nodiscard]] bool empty() const { @@ -112,35 +164,101 @@ public: // 检查是否包含指定key [[nodiscard]] bool contains(const Key& key) const { std::shared_lock lock(mutex_); - return cache_map_.contains(key); + return cache_map_.contains(key); // C++20 feature } - // 范围for循环支持 - auto begin() const { - std::shared_lock lock(mutex_); - return cache_list_.begin(); - } + // 提供线程安全的迭代器包装 + class const_iterator { + const lru_cache* cache_; + list_iterator iter_; + std::shared_lock lock_; - auto end() const { - std::shared_lock lock(mutex_); - return cache_list_.end(); - } + public: + using iterator_category = std::forward_iterator_tag; + using value_type = key_value_pair_t; + using difference_type = std::ptrdiff_t; + using pointer = const key_value_pair_t*; + using reference = const key_value_pair_t&; + + const_iterator(const lru_cache* cache, list_iterator iter) : cache_(cache), iter_(iter), lock_(cache->mutex_) {} + + reference operator*() const { return *iter_; } + pointer operator->() const { return &(*iter_); } + + const_iterator& operator++() { + ++iter_; + return *this; + } + + const_iterator operator++(int) { + const_iterator tmp = *this; + ++(*this); + return tmp; + } + + bool operator==(const const_iterator& other) const { return iter_ == other.iter_; } + + bool operator!=(const const_iterator& other) const { return !(*this == other); } + }; + + // 线程安全的迭代器 + const_iterator begin() const { return const_iterator(this, cache_list_.begin()); } + + const_iterator end() const { return const_iterator(this, cache_list_.end()); } // 调整缓存容量 void resize(std::size_t new_capacity) { - if (new_capacity == 0) { + if (new_capacity == 0) { // 修复了语法错误 throw std::invalid_argument("Cache capacity must be greater than 0"); } std::unique_lock lock(mutex_); while (cache_list_.size() > new_capacity) { - auto last = cache_list_.end(); - --last; + auto last = std::prev(cache_list_.end()); cache_map_.erase(last->first); cache_list_.pop_back(); } capacity_ = new_capacity; } + + // 批量操作支持 + template + void put_range(InputIt first, InputIt last) { + std::unique_lock lock(mutex_); + + for (auto it = first; it != last; ++it) { + // 内部实现,避免重复加锁 + auto map_it = cache_map_.find(it->first); + if (map_it != cache_map_.end()) { + map_it->second->second = it->second; + cache_list_.splice(cache_list_.begin(), cache_list_, map_it->second); + } + else { + if (cache_list_.size() >= capacity_) { + auto last_elem = std::prev(cache_list_.end()); + cache_map_.erase(last_elem->first); + cache_list_.pop_back(); + } + cache_list_.emplace_front(it->first, it->second); + cache_map_.emplace(it->first, cache_list_.begin()); + } + } + } + + // 获取缓存统计信息 + struct cache_stats { + std::size_t size; + std::size_t capacity; + double fill_ratio; + }; + + [[nodiscard]] cache_stats get_stats() const { + std::shared_lock lock(mutex_); + std::size_t current_size = cache_list_.size(); + return { .size = current_size, + .capacity = capacity_, + .fill_ratio = static_cast(current_size) / capacity_ }; + } }; diff --git a/src/mirage_render/font/freetype_font/freetype b/src/mirage_render/font/freetype_font/freetype index 42a649b..82090e6 160000 --- a/src/mirage_render/font/freetype_font/freetype +++ b/src/mirage_render/font/freetype_font/freetype @@ -1 +1 @@ -Subproject commit 42a649be4929444f4c42763ac8704a3c2f22f9f7 +Subproject commit 82090e67c24259c343c83fd9cefe6ff0be7a7eca diff --git a/src/mirage_render/font/freetype_font/harfbuzz b/src/mirage_render/font/freetype_font/harfbuzz index e1dcc45..9f83bbb 160000 --- a/src/mirage_render/font/freetype_font/harfbuzz +++ b/src/mirage_render/font/freetype_font/harfbuzz @@ -1 +1 @@ -Subproject commit e1dcc454f153fe2c006fc0354ade819770549ea2 +Subproject commit 9f83bbbe64654b45ba5bb06927ff36c2e7588495 diff --git a/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.cpp b/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.cpp index 1bfa63c..eaae2e7 100644 --- a/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.cpp +++ b/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.cpp @@ -126,6 +126,14 @@ std::shared_ptr stb_font_face_t::get_emoji_image(int32_t in_glyph_ return nullptr; } +bool stb_font_face_t::has_glyph_index(uint32_t in_glyph_index) const { + if (in_glyph_index == 0) { + return false; // 0通常表示无效的字形索引 + } + // 检查字形索引是否存在 + return stbtt_IsGlyphEmpty(&font_info_, in_glyph_index) == 0; +} + uint32_t stb_font_face_t::find_glyph_index(uint32_t in_unicode_codepoint) const { return stbtt_FindGlyphIndex(&font_info_, in_unicode_codepoint); } diff --git a/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.h b/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.h index e3483e8..1175491 100644 --- a/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.h +++ b/src/mirage_render/font/stb_truetype_font/stb_truetype_interface.h @@ -11,6 +11,7 @@ public: [[nodiscard]] font_v_metrics_t get_metrics_impl() const override; [[nodiscard]] std::shared_ptr get_glyph_image(int32_t in_glyph_id) const override; [[nodiscard]] std::shared_ptr get_emoji_image(int32_t in_glyph_id) const override; + virtual bool has_glyph_index(uint32_t in_glyph_index) const override; [[nodiscard]] uint32_t find_glyph_index(uint32_t in_unicode_codepoint) const override; [[nodiscard]] float get_kerning(uint32_t in_first_glyph_id, uint32_t in_second_glyph_id) const override; [[nodiscard]] glyph_shaped_t make_shape_glyph(uint32_t in_glyph_id) const override; diff --git a/src/mirage_render/src/font/font_layout.cpp b/src/mirage_render/src/font/font_layout.cpp index bf63aee..a9df90d 100644 --- a/src/mirage_render/src/font/font_layout.cpp +++ b/src/mirage_render/src/font/font_layout.cpp @@ -3,6 +3,7 @@ #include "emoji_detector.h" #include "font_system.h" #include "interface/font_interface.h" +#include "misc/log_util.h" namespace text_layout_impl { // 临时存储待处理字形的信息 @@ -212,8 +213,49 @@ void font_manager::append_layout_text(text_layout_t& in_layout, in_layout.total_size = { total_width, total_height }; } -void text_layout_t::line_t::format() { +void text_layout_t::line_t::format(const font_face_ptr& in_primary_font, float in_font_size) { + auto& font_mgr = font_manager::instance(); + in_primary_font->set_font_size(in_font_size); + line_height = in_primary_font ? in_primary_font->get_metrics().line_height : font_mgr.get_primary_font()->get_metrics().line_height; + glyph_position_t* prev_g = nullptr; + uint32_t prev_glyph_index = 0; + float cursor_x = 0.0f; + + for (auto& g : glyphs) { + uint32_t glyph_index; + font_face_ptr using_font = font_mgr.get_font_for_code_point(in_primary_font, g.codepoint, &glyph_index); + if (!using_font) { + log_warn("Glyph index {} not found in any font for codepoint U+{:04X}.", glyph_index, g.codepoint); + } + + const auto is_emoji = emoji_detector::is_emoji(glyph_index); + const auto& metrics = using_font->get_metrics(); + line_height = std::max(line_height, metrics.line_height); + + g.is_emoji = is_emoji; + g.region = font_mgr.get_or_create_glyph_by_index(glyph_index, using_font, in_font_size, is_emoji); + + auto g_metrics = using_font->shape_glyph(glyph_index); + + float kerning = 0.0f; + if (prev_g) { + kerning = using_font->get_kerning(prev_glyph_index, glyph_index); + } + + g.position.x() = cursor_x + kerning + g_metrics.offset.x(); + + const float size_y_diff = g_metrics.rect.size().y() - static_cast(g.region->rect.size().y()); + const float baseline_y = position_y + metrics.ascent + (line_height - metrics.line_height) / 2.0f; + g.position.y() = baseline_y + g_metrics.offset.y() + size_y_diff; + + cursor_x += kerning + g_metrics.advance.x(); + + prev_g = &g; + prev_glyph_index = glyph_index; + } + + line_width = cursor_x; } void text_layout_t::push_str(const std::u32string& str) { @@ -223,54 +265,60 @@ void text_layout_t::push_str(const std::u32string& str) { } auto& cursor_y = last_cursor.y(); - auto& cursor_x = last_cursor.x(); + auto* current_line = &get_last_line(); - const auto& metrics = primary_font->get_metrics(); - const auto default_line_height = metrics.line_height; + auto end_line = [&](bool new_line) { + current_line->position_y = cursor_y; + current_line->format(primary_font, font_size); + if (new_line) { + cursor_y += current_line->get_line_height() * line_spacing; + current_line = &next_line(); + } + }; for (const auto c : str) { if (c == U'\n') { - cursor_x = 0.0f; - cursor_y += default_line_height * line_spacing; - total_size.y() += default_line_height * line_spacing; + end_line(true); continue; } - auto* line = &get_last_line(); - bool at_line_start = line->empty(); - auto glyph_info = text_layout_impl::get_glyph_info(c, primary_font); - // 如果没有找到有效的字体或字形,跳过 - if (!glyph_info.font) - continue; + glyph_position_t p{}; + p.codepoint = c; + current_line->add_glyph(p); + } - // 计算间距和位置 - auto kerning = line->glyphs.empty() - ? 0.0f - : primary_font->get_kerning(line->glyphs.back().glyph_index, glyph_info.glyph_index); - const auto next_x = cursor_x + kerning + glyph_info.metrics.advance.x(); + end_line(false); // 确保最后一行也被格式化 - // 检查换行 - if (text_layout_impl::should_wrap_line(max_width, next_x, !line->empty())) { - line = &next_line(); - kerning = 0.f; - } - - line->max_ascent = std::max(line->max_ascent, metrics.ascent); - line->max_descent = std::max(line->max_descent, metrics.descent); - - cursor_x += kerning; - - glyph_position_t glyph_position; - glyph_position.is_emoji = glyph_info.is_emoji; - glyph_position.glyph_index = glyph_info.glyph_index; - glyph_position.position = { cursor_x + glyph_info.metrics.offset.x(), - cursor_y + glyph_info.metrics.offset.y() }; - glyph_position.region = glyph_info.region; - line->add_glyph(glyph_position); - - cursor_x += glyph_info.metrics.advance.x(); - - line->position_y = cursor_y; - line->line_width = cursor_x; + total_size.y() += cursor_y; + for (const auto& line: lines) { + total_size.x() = std::max(total_size.x(), line.line_width); } } + +void text_layout_t::set_font_size(float size) { + if (font_size == size) { + return; // 如果字体大小没有变化,直接返回 + } + + font_size = size; + if (override_primary_font) { + override_primary_font->set_font_size(size); + } + total_size.setZero(); // 重置总大小 + last_cursor.setZero(); // 重置光标位置 + clear(); // 清除现有内容 +} + +void text_layout_t::set_primary_font(const font_face_ptr& font) { + override_primary_font = font; + clear(); // 清除现有内容 +} + +float text_layout_t::get_empty_line_height() const { + const auto font = override_primary_font ? override_primary_font : font_manager::instance().get_primary_font(); + if (!font) { + return 0.0f; // 如果没有主字体,返回0 + } + font->set_font_size(font_size); + return font->get_metrics().line_height * line_spacing; +} diff --git a/src/mirage_render/src/font/font_layout.h b/src/mirage_render/src/font/font_layout.h index 730e082..5b7b97b 100644 --- a/src/mirage_render/src/font/font_layout.h +++ b/src/mirage_render/src/font/font_layout.h @@ -21,30 +21,48 @@ struct text_layout_t { } struct glyph_position_t { bool is_emoji; // 是否为表情符号 - uint32_t glyph_index; // 字形索引 + uint32_t codepoint; Eigen::Vector2f position; // 屏幕位置 std::shared_ptr region; // 纹理图集区域 }; struct line_t { - float max_ascent = 0.0f; // 最大上升高度 - float max_descent = 0.0f; + float line_height = 0.0f; // 行高 float position_y = 0.0f; // 行的Y位置 float line_width = 0.0f; // 行的宽度 std::vector glyphs; - auto get_line_size() const { - return Eigen::Vector2f(line_width, max_ascent + max_descent); + [[nodiscard]] auto get_line_height() const { + return line_height; + } + [[nodiscard]] auto get_line_size() const { + return Eigen::Vector2f(line_width, get_line_height()); } void add_glyph(const glyph_position_t& glyph) { glyphs.emplace_back(glyph); } - bool empty() const { + [[nodiscard]] bool empty() const { return glyphs.empty(); } - void format(); + void format(const font_face_ptr& in_primary_font, float in_font_size); }; + line_t* get_line(size_t index) { + if (index < lines.size()) { + return &lines[index]; + } + return nullptr; + } + [[nodiscard]] const line_t* get_line(size_t index) const { + if (index < lines.size()) { + return &lines[index]; + } + return nullptr; + } + + [[nodiscard]] size_t size() const { + return lines.size(); + } auto& get_last_line() { return lines.back(); } @@ -58,16 +76,35 @@ struct text_layout_t { } void push_str(const std::u32string& str); + void clear() { + lines.clear(); + lines.emplace_back(); // 重新初始化第一行 + total_size.setZero(); + last_cursor.setZero(); + } void add_glyph(const glyph_position_t& glyph) { auto& last_line = get_last_line(); last_line.add_glyph(glyph); } - std::vector lines; // 文本行列表 - float max_width; - float line_spacing = 1.2f; // 行间距 - Eigen::Vector2f total_size{ 0, 0 }; // 文本总尺寸 - Eigen::Vector2f last_cursor{ 0, 0 }; // 最后光标位置 - font_face_ptr override_primary_font; // 主字体 + void set_font_size(float size); + void set_primary_font(const font_face_ptr& font); + float get_empty_line_height() const; + + auto begin() { return lines.begin(); } + auto begin() const { return lines.begin(); } + auto end() { return lines.end(); } + auto end() const { return lines.end(); } + + Eigen::Vector2f total_size{ 0, 0 }; // 文本总尺寸 + Eigen::Vector2f last_cursor{ 0, 0 }; // 最后光标位置 +private: + float max_width = 0.f; + float line_spacing = 1.2f; // 行间距 + float font_size = 24.f; // 字体大小 + float empty_line_height = 0.f; // 空行高度 + + std::vector lines; // 文本行列表 + font_face_ptr override_primary_font; // 主字体 }; diff --git a/src/mirage_render/src/interface/font_interface.cpp b/src/mirage_render/src/interface/font_interface.cpp index db3d33a..20f670b 100644 --- a/src/mirage_render/src/interface/font_interface.cpp +++ b/src/mirage_render/src/interface/font_interface.cpp @@ -1,17 +1,5 @@ #include "font_interface.h" -template<> -struct std::hash { - size_t operator()(const font_face_interface::glyph_key& key) const noexcept { - // 根据 glyph_key 的成员变量计算 hash - // 示例(需要根据实际成员调整): - size_t h1 = std::hash{}(key.glyph_id); - size_t h2 = std::hash{}(key.font_size); - // 组合多个 hash 值 - return h1 ^ (h2 << 1); - } -}; - bool font_face_interface::load(const std::filesystem::path& in_path) { font_data_ = mapped_file::create(); if (!font_data_->map_file(in_path)) { diff --git a/src/mirage_render/src/interface/font_interface.h b/src/mirage_render/src/interface/font_interface.h index e0d7a06..72b6568 100644 --- a/src/mirage_render/src/interface/font_interface.h +++ b/src/mirage_render/src/interface/font_interface.h @@ -31,16 +31,30 @@ struct glyph_shaped_t { rect_t<> rect; // 字形矩形区域 }; +struct glyph_key { + uint32_t glyph_id; + float font_size; + + bool operator==(const glyph_key& other) const { return glyph_id == other.glyph_id && font_size == other.font_size; } +}; + +// 为 glyph_key 提供 std::hash 特化 +template<> +struct std::hash { + std::size_t operator()(const glyph_key& key) const noexcept { + // 组合哈希值的常用方法 + const std::size_t h1 = std::hash{}(key.glyph_id); + const std::size_t h2 = std::hash{}(key.font_size); + + // 使用魔法数字组合哈希值,避免简单的异或 + return h1 ^ (h2 << 1); // 或者使用 boost::hash_combine 的方法 + // return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); + } +}; + class font_face_interface { public: - struct glyph_key { - uint32_t glyph_id; - float font_size; - bool operator==(const glyph_key& other) const { - return glyph_id == other.glyph_id && font_size == other.font_size; - } - }; virtual ~font_face_interface() = default; bool load(const std::filesystem::path& in_path); @@ -66,10 +80,11 @@ public: [[nodiscard]] virtual std::shared_ptr get_glyph_image(int32_t in_glyph_id) const = 0; [[nodiscard]] virtual std::shared_ptr get_emoji_image(int32_t in_glyph_id) const = 0; + [[nodiscard]] virtual bool has_glyph_index(uint32_t in_glyph_index) const = 0; [[nodiscard]] virtual uint32_t find_glyph_index(uint32_t in_unicode_codepoint) const = 0; [[nodiscard]] virtual bool has_glyph(uint32_t in_unicode_codepoint) const { return find_glyph_index(in_unicode_codepoint) > 0; } - [[nodiscard]] virtual float get_kerning(uint32_t in_first_glyph_id, uint32_t in_second_glyph_id) const = 0; + [[nodiscard]] virtual float get_kerning(uint32_t in_first_glyph_id, uint32_t in_second_glyph_id) const = 0; [[nodiscard]] glyph_shaped_t shape_glyph(uint32_t in_glyph_id) const { if (in_glyph_id == 0) { return {}; diff --git a/src/mirage_render/src/render/render_elements.cpp b/src/mirage_render/src/render/render_elements.cpp index b84655f..fdf939b 100644 --- a/src/mirage_render/src/render/render_elements.cpp +++ b/src/mirage_render/src/render/render_elements.cpp @@ -279,14 +279,14 @@ void render_elements::make_text(const text_layout_t& in_layout, const Eigen::Vec const auto& glyph_sampler = texture_sampler_builder::get_sampler(sampler_type::pixel_art); const auto& emoji_sampler = texture_sampler_builder::get_sampler(sampler_type::anisotropic); - for (const auto& line : in_layout.lines) { + for (const auto& line : in_layout) { for (const auto& position : line.glyphs) { const auto& p = position; const auto& region = p.region; - const auto& size = region.rect.size().cast(); - const auto& uv = region.uv_rect; + const auto& size = region->rect.size().cast(); + const auto& uv = region->uv_rect; - if (const auto& texture = region.texture.lock()) { + if (const auto& texture = region->texture.lock()) { // 构建完整的批次键 batch_key new_key; new_key.pipeline = position.is_emoji ? image_pipeline_ : text_pipeline_; diff --git a/src/mirage_widget/src/widget/leaf_widget/meditable_text_box.cpp b/src/mirage_widget/src/widget/leaf_widget/meditable_text_box.cpp index 73f4846..076078e 100644 --- a/src/mirage_widget/src/widget/leaf_widget/meditable_text_box.cpp +++ b/src/mirage_widget/src/widget/leaf_widget/meditable_text_box.cpp @@ -46,7 +46,7 @@ void meditable_text_box::on_paint(mirage_paint_context& in_context) { { { 0.1f, 0.1f, 0.1f, 1.f } }, { round_ } ); - auto text_y = (in_context.geo().get_local_size().y() - layout_.total_size.y()) / 2 + round_; + auto text_y = round_; // 绘制文本 in_context.drawer().make_text( layout_, @@ -55,8 +55,9 @@ void meditable_text_box::on_paint(mirage_paint_context& in_context) { in_context.geo() ); if (is_focus()) { - const float line_height = layout_.get_last_line().line_height; - const auto& cursor_pos = layout_.last_cursor + Eigen::Vector2f(round_, round_); + const float line_height = layout_.get_last_line().get_line_height(); + const float line_width = layout_.get_last_line().line_width; + const auto& cursor_pos = Eigen::Vector2f(line_width, layout_.get_last_line().position_y) + Eigen::Vector2f(round_, round_); // 绘制光标 in_context.drawer().make_rounded_rect( cursor_pos, @@ -72,7 +73,7 @@ void meditable_text_box::on_paint(mirage_paint_context& in_context) { auto meditable_text_box::compute_desired_size(float in_layout_scale_multiplier) const -> Eigen::Vector2f { return no_warp_size_ .cwiseMax(layout_.total_size) - .cwiseMax(Eigen::Vector2f(0, layout_.get_last_line().line_height)) + .cwiseMax(Eigen::Vector2f(0, layout_.get_empty_line_height())) + Eigen::Vector2f(0, round_ * 2); } @@ -144,7 +145,10 @@ void meditable_text_box::update_layout(const geometry_t& in_geometry, bool in_la invalidate(invalidate_reason::layout); } - layout_ = font_manager::instance().layout_text(temp_text_, font_, font_size_, max_width, line_spacing_); + // layout_ = font_manager::instance().layout_text(temp_text_, font_, font_size_, max_width, line_spacing_); + layout_.set_font_size(font_size_); + layout_.clear(); + layout_.push_str(temp_text_); no_warp_size_ = font_manager::instance().layout_text(temp_text_, font_, font_size_, 0, line_spacing_).total_size; if (in_layout_validate) { invalidate(invalidate_reason::layout);