diff options
author | crupest <crupest@outlook.com> | 2020-03-01 22:32:58 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-03-01 22:32:58 +0800 |
commit | f23077eb0ddff77b7e114994f967189ea7607600 (patch) | |
tree | 9d27ccf8d721d40f8829ae2458e67a60eaaed25d | |
parent | 6e0e0e18cbeff6487160c84d71997575f6cccebd (diff) | |
download | cru-f23077eb0ddff77b7e114994f967189ea7607600.tar.gz cru-f23077eb0ddff77b7e114994f967189ea7607600.tar.bz2 cru-f23077eb0ddff77b7e114994f967189ea7607600.zip |
Complete hit test in text layout.
-rw-r--r-- | include/cru/platform/graph/text_layout.hpp | 8 | ||||
-rw-r--r-- | include/cru/win/graph/direct/text_layout.hpp | 2 | ||||
-rw-r--r-- | src/win/graph/direct/text_layout.cpp | 38 |
3 files changed, 44 insertions, 4 deletions
diff --git a/include/cru/platform/graph/text_layout.hpp b/include/cru/platform/graph/text_layout.hpp index 4f6e81e1..d1cfb44b 100644 --- a/include/cru/platform/graph/text_layout.hpp +++ b/include/cru/platform/graph/text_layout.hpp @@ -8,6 +8,12 @@ namespace cru::platform::graph { struct IFont; +struct TextHitTestResult { + int position; + bool trailing; + bool insideText; +}; + struct ITextLayout : virtual IGraphResource { virtual std::string GetText() = 0; virtual void SetText(std::string new_text) = 0; @@ -20,5 +26,7 @@ struct ITextLayout : virtual IGraphResource { virtual Rect GetTextBounds() = 0; virtual std::vector<Rect> TextRangeRect(const TextRange& text_range) = 0; + virtual Point TextSingleRect(int position, bool trailing) = 0; + virtual TextHitTestResult HitTest(const Point& point) = 0; }; } // namespace cru::platform::graph diff --git a/include/cru/win/graph/direct/text_layout.hpp b/include/cru/win/graph/direct/text_layout.hpp index 5a8f3f9c..5f7be9f3 100644 --- a/include/cru/win/graph/direct/text_layout.hpp +++ b/include/cru/win/graph/direct/text_layout.hpp @@ -38,6 +38,8 @@ class DWriteTextLayout : public DirectGraphResource, Rect GetTextBounds() override; std::vector<Rect> TextRangeRect(const TextRange& text_range) override; + Point TextSingleRect(int position, bool trailing) override; + TextHitTestResult HitTest(const Point& point) override; private: std::string text_; diff --git a/src/win/graph/direct/text_layout.cpp b/src/win/graph/direct/text_layout.cpp index a070d288..ecee1727 100644 --- a/src/win/graph/direct/text_layout.cpp +++ b/src/win/graph/direct/text_layout.cpp @@ -80,10 +80,10 @@ std::vector<Rect> DWriteTextLayout::TextRangeRect(const TextRange& text_range) { std::vector<DWRITE_HIT_TEST_METRICS> hit_test_metrics(metrics_count); UINT32 actual_count; - text_layout_->HitTestTextRange(static_cast<UINT32>(start_index), - static_cast<UINT32>(end_index - start_index), - 0, 0, hit_test_metrics.data(), metrics_count, - &actual_count); + ThrowIfFailed(text_layout_->HitTestTextRange( + static_cast<UINT32>(start_index), + static_cast<UINT32>(end_index - start_index), 0, 0, + hit_test_metrics.data(), metrics_count, &actual_count)); hit_test_metrics.erase(hit_test_metrics.cbegin() + actual_count, hit_test_metrics.cend()); @@ -99,4 +99,34 @@ std::vector<Rect> DWriteTextLayout::TextRangeRect(const TextRange& text_range) { return result; } + +Point DWriteTextLayout::TextSingleRect(int position, bool trailing) { + const auto index = + IndexUtf8ToUtf16(text_, static_cast<int>(position), w_text_); + + DWRITE_HIT_TEST_METRICS metrics; + FLOAT left; + FLOAT top; + ThrowIfFailed(text_layout_->HitTestTextPosition(static_cast<UINT32>(index), + static_cast<BOOL>(trailing), + &left, &top, &metrics)); + return Point{left, top}; +} + +TextHitTestResult DWriteTextLayout::HitTest(const Point& point) { + BOOL trailing; + BOOL inside; + DWRITE_HIT_TEST_METRICS metrics; + + ThrowIfFailed(text_layout_->HitTestPoint(point.x, point.y, &trailing, &inside, + &metrics)); + + const auto index = + IndexUtf16ToUtf8(w_text_, static_cast<int>(metrics.textPosition), text_); + TextHitTestResult result; + result.position = index; + result.trailing = trailing != 0; + result.insideText = inside != 0; + return result; +} } // namespace cru::platform::graph::win::direct |