diff options
| -rw-r--r-- | include/cru/platform/graphics/Base.h | 1 | ||||
| -rw-r--r-- | src/platform/graphics/cairo/PangoTextLayout.cpp | 14 | ||||
| -rw-r--r-- | src/platform/graphics/direct2d/TextLayout.cpp | 16 | ||||
| -rw-r--r-- | src/platform/graphics/quartz/TextLayout.cpp | 18 | ||||
| -rw-r--r-- | src/ui/controls/TextHostControlService.cpp | 20 |
5 files changed, 48 insertions, 21 deletions
diff --git a/include/cru/platform/graphics/Base.h b/include/cru/platform/graphics/Base.h index 7f12dbef..371d0f99 100644 --- a/include/cru/platform/graphics/Base.h +++ b/include/cru/platform/graphics/Base.h @@ -31,6 +31,7 @@ struct TextHitTestResult { Index position; bool trailing; bool inside_text; + Index position_with_trailing; }; struct CRU_PLATFORM_GRAPHICS_API IGraphicsResource : virtual IPlatformResource { diff --git a/src/platform/graphics/cairo/PangoTextLayout.cpp b/src/platform/graphics/cairo/PangoTextLayout.cpp index 9d301031..25d9f85d 100644 --- a/src/platform/graphics/cairo/PangoTextLayout.cpp +++ b/src/platform/graphics/cairo/PangoTextLayout.cpp @@ -160,7 +160,19 @@ TextHitTestResult PangoTextLayout::HitTest(const Point& point) { auto inside_text = pango_layout_xy_to_index(pango_layout_, point.x * PANGO_SCALE, point.y * PANGO_SCALE, &index, &trailing); - return TextHitTestResult{index, trailing != 0, inside_text != 0}; + + TextHitTestResult result{index, trailing != 0, inside_text != 0}; + + if (result.trailing) { + Index position_with_trailing; + string::Utf8NextCodePoint(text_.data(), text_.size(), result.position, + &position_with_trailing); + result.position_with_trailing = position_with_trailing; + } else { + result.position_with_trailing = result.position; + } + + return result; } } // namespace cru::platform::graphics::cairo diff --git a/src/platform/graphics/direct2d/TextLayout.cpp b/src/platform/graphics/direct2d/TextLayout.cpp index d347e0f7..be9d75ff 100644 --- a/src/platform/graphics/direct2d/TextLayout.cpp +++ b/src/platform/graphics/direct2d/TextLayout.cpp @@ -154,8 +154,8 @@ Rect DWriteTextLayout::TextSinglePoint(Index position, bool trailing) { FLOAT left; FLOAT top; CheckHResult(text_layout_->HitTestTextPosition(static_cast<UINT32>(position), - static_cast<BOOL>(trailing), - &left, &top, &metrics)); + static_cast<BOOL>(trailing), + &left, &top, &metrics)); return Rect{left, top, 0, GetFont()->GetFontSize()}; } @@ -165,7 +165,7 @@ TextHitTestResult DWriteTextLayout::HitTest(const Point& point) { DWRITE_HIT_TEST_METRICS metrics; CheckHResult(text_layout_->HitTestPoint(point.x, point.y, &trailing, &inside, - &metrics)); + &metrics)); TextHitTestResult result; result.position = string::Utf8IndexCodePointToCodeUnit( @@ -174,6 +174,16 @@ TextHitTestResult DWriteTextLayout::HitTest(const Point& point) { reinterpret_cast<const char16_t*>(utf16_text_.data()), utf16_text_.size(), metrics.textPosition)); result.trailing = trailing != 0; + + if (result.trailing) { + Index position_with_trailing; + string::Utf8NextCodePoint(text_.data(), text_.size(), result.position, + &position_with_trailing); + result.position_with_trailing = position_with_trailing; + } else { + result.position_with_trailing = result.position; + } + return result; } } // namespace cru::platform::graphics::direct2d diff --git a/src/platform/graphics/quartz/TextLayout.cpp b/src/platform/graphics/quartz/TextLayout.cpp index f98cff3a..4793a19c 100644 --- a/src/platform/graphics/quartz/TextLayout.cpp +++ b/src/platform/graphics/quartz/TextLayout.cpp @@ -180,11 +180,11 @@ Rect OsxCTTextLayout::TextSinglePoint(Index position, bool trailing) { TextHitTestResult OsxCTTextLayout::HitTest(const Point& point) { if (point.y < head_empty_line_count_ * font_->GetFontSize()) { if (point.y < 0) { - return {0, false, false}; + return {0, false, false, 0}; } else { for (int i = 1; i <= head_empty_line_count_; ++i) { if (point.y < i * font_->GetFontSize()) { - return {i - 1, false, false}; + return {i - 1, false, false, i - 1}; } } } @@ -197,11 +197,14 @@ TextHitTestResult OsxCTTextLayout::HitTest(const Point& point) { if (point.y >= th) { for (int i = 1; i <= tail_empty_line_count_; ++i) { if (point.y < th + i * font_->GetFontSize()) { - return {static_cast<Index>(text_.size() - (tail_empty_line_count_ - i)), - false, false}; + return { + static_cast<Index>(text_.size() - (tail_empty_line_count_ - i)), + false, false, + static_cast<Index>(text_.size() - (tail_empty_line_count_ - i))}; } } - return {static_cast<Index>(text_.size()), false, false}; + return {static_cast<Index>(text_.size()), false, false, + static_cast<Index>(text_.size())}; } auto p = point; @@ -261,11 +264,12 @@ TextHitTestResult OsxCTTextLayout::HitTest(const Point& point) { --po; } - return {po + head_empty_line_count_, false, inside_text}; + return {po + head_empty_line_count_, false, inside_text, + po + head_empty_line_count_}; } } - return TextHitTestResult{0, false, false}; + return TextHitTestResult{0, false, false, 0}; } void OsxCTTextLayout::ReleaseResource() { diff --git a/src/ui/controls/TextHostControlService.cpp b/src/ui/controls/TextHostControlService.cpp index f581d3c9..b2fbd61d 100644 --- a/src/ui/controls/TextHostControlService.cpp +++ b/src/ui/controls/TextHostControlService.cpp @@ -68,7 +68,7 @@ TextControlMovePattern TextControlMovePattern::kUp( auto rect = text_render_object->TextSinglePoint(current_position, false); rect.top -= 0.1f; auto result = text_render_object->TextHitTest(rect.GetLeftTop()); - return result.trailing ? result.position + 1 : result.position; + return result.position_with_trailing; }); TextControlMovePattern TextControlMovePattern::kDown( "Down", helper::ShortcutKeyBind(platform::gui::KeyCode::Down), @@ -79,7 +79,7 @@ TextControlMovePattern TextControlMovePattern::kDown( auto rect = text_render_object->TextSinglePoint(current_position, false); rect.top += rect.height + 0.1f; auto result = text_render_object->TextHitTest(rect.GetLeftTop()); - return result.trailing ? result.position + 1 : result.position; + return result.position_with_trailing; }); TextControlMovePattern TextControlMovePattern::kHome( "Home(Line Begin)", helper::ShortcutKeyBind(platform::gui::KeyCode::Home), @@ -241,7 +241,7 @@ void TextHostControlService::InsertText(Index position, std::string_view text, void TextHostControlService::DeleteChar(Index position, bool stop_composition) { if (!Utf8IsValidInsertPosition(this->text_.data(), this->text_.size(), position)) { - CRU_LOG_TAG_ERROR("Invalid text delete position."); + CRU_LOG_TAG_ERROR("Invalid text delete position {}.", position); return; } if (position == static_cast<Index>(this->text_.size())) return; @@ -255,7 +255,7 @@ Index TextHostControlService::DeleteCharPrevious(Index position, bool stop_composition) { if (!Utf8IsValidInsertPosition(this->text_.data(), this->text_.size(), position)) { - CRU_LOG_TAG_ERROR("Invalid text delete position."); + CRU_LOG_TAG_ERROR("Invalid text delete position {}.", position); return 0; } if (position == 0) return 0; @@ -273,12 +273,12 @@ void TextHostControlService::DeleteText(TextRange range, range = range.Normalize(); if (!Utf8IsValidInsertPosition(this->text_.data(), this->text_.size(), range.GetStart())) { - CRU_LOG_TAG_ERROR("Invalid text delete start position."); + CRU_LOG_TAG_ERROR("Invalid text delete start position {}.", range.GetStart()); return; } if (!Utf8IsValidInsertPosition(this->text_.data(), this->text_.size(), - range.GetStart())) { - CRU_LOG_TAG_ERROR("Invalid text delete end position."); + range.GetEnd())) { + CRU_LOG_TAG_ERROR("Invalid text delete end position {}.", range.GetEnd()); return; } this->text_.erase(this->text_.cbegin() + range.GetStart(), @@ -490,7 +490,7 @@ void TextHostControlService::MouseDownHandler( const auto text_render_object = this->GetTextRenderObject(); const auto result = text_render_object->TextHitTest( args.GetPointToContent(text_render_object)); - const auto position = result.position + (result.trailing ? 1 : 0); + const auto position = result.position_with_trailing; SetSelection(position); args.SetHandled(true); } else if (args.GetButton() == MouseButtons::Right) { @@ -525,7 +525,7 @@ void TextHostControlService::MouseDownHandler( const auto text_render_object = this->GetTextRenderObject(); const auto result = text_render_object->TextHitTest( args.GetPointToContent(text_render_object)); - const auto position = result.position + (result.trailing ? 1 : 0); + const auto position = result.position_with_trailing; SetSelection(position); ContextMenuItem items = ContextMenuItem::kSelectAll; @@ -554,7 +554,7 @@ void TextHostControlService::MouseMoveHandler(events::MouseEventArgs& args) { const auto text_render_object = this->GetTextRenderObject(); const auto result = text_render_object->TextHitTest( args.GetPointToContent(text_render_object)); - const auto position = result.position + (result.trailing ? 1 : 0); + const auto position = result.position_with_trailing; ChangeSelectionEnd(position); args.SetHandled(); } |
