Fix editor text caret measurement

This commit is contained in:
2026-04-23 01:43:23 +08:00
parent 82c39e2521
commit 514dee10cc
24 changed files with 205 additions and 62 deletions

View File

@@ -1,5 +1,7 @@
#pragma once
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <XCEngine/UI/Text/UITextEditing.h>
#include <XCEngine/UI/DrawData.h>
@@ -37,7 +39,18 @@ inline ::XCEngine::UI::UIRect ResolveUIEditorTextClipRect(
inline float MeasureUIEditorTextWidth(
const std::string& text,
float fontSize) {
float fontSize,
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr) {
if (textMeasurer != nullptr &&
!text.empty() &&
fontSize > 0.0f) {
return textMeasurer->MeasureTextWidth(
::XCEngine::UI::Editor::UIEditorTextMeasureRequest{
text,
fontSize
});
}
return fontSize * 0.56f *
static_cast<float>(::XCEngine::UI::Text::CountUtf8Codepoints(text));
}
@@ -45,12 +58,24 @@ inline float MeasureUIEditorTextWidth(
inline float MeasureUIEditorTextWidthToCaret(
const std::string& text,
std::size_t caretOffset,
float fontSize) {
float fontSize,
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr) {
const std::size_t clampedCaretOffset = (std::min)(caretOffset, text.size());
if (textMeasurer != nullptr &&
clampedCaretOffset > 0u &&
fontSize > 0.0f) {
return textMeasurer->MeasureTextWidth(
::XCEngine::UI::Editor::UIEditorTextMeasureRequest{
std::string_view(text.data(), clampedCaretOffset),
fontSize
});
}
return fontSize * 0.56f *
static_cast<float>(::XCEngine::UI::Text::CountUtf8CodepointsInRange(
text,
0u,
(std::min)(caretOffset, text.size())));
clampedCaretOffset));
}
inline std::uint64_t GetUIEditorTextCaretClockNanoseconds() {
@@ -93,14 +118,20 @@ inline void AppendUIEditorTextCaret(
float fontSize,
float insetX,
float insetY = 0.0f,
float thickness = 1.0f) {
float thickness = 1.0f,
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr) {
if (color.a <= 0.0f || !ShouldBlinkUIEditorTextCaret(blinkStartNanoseconds)) {
return;
}
const float caretX = (std::min)(
rect.x + rect.width - 1.0f,
rect.x + insetX + MeasureUIEditorTextWidthToCaret(text, caretOffset, fontSize));
rect.x + insetX +
MeasureUIEditorTextWidthToCaret(
text,
caretOffset,
fontSize,
textMeasurer));
const float top = ResolveUIEditorTextTop(rect, fontSize, insetY);
const float bottom = top + MeasureUIEditorTextLayoutHeight(fontSize);
drawList.AddLine(