1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#include "cru/platform/win/win_text_layout.hpp"
#include "cru/platform/win/exception.hpp"
#include "cru/platform/win/graph_manager.hpp"
#include <cassert>
#include <utility>
namespace cru::platform::win {
WinTextLayout::WinTextLayout(GraphManager* graph_manager,
std::shared_ptr<WinFontDescriptor> font,
std::wstring text) {
assert(graph_manager);
assert(font);
graph_manager_ = graph_manager;
text_.swap(text);
font_descriptor_.swap(font);
ThrowIfFailed(graph_manager_->GetDWriteFactory()->CreateTextLayout(
text_.c_str(), text_.size(), font_descriptor_->GetDWriteTextFormat(),
max_width_, max_height_, &text_layout_));
}
std::wstring WinTextLayout::GetText() { return text_; }
void WinTextLayout::SetText(std::wstring new_text) {
text_.swap(new_text);
ThrowIfFailed(graph_manager_->GetDWriteFactory()->CreateTextLayout(
text_.c_str(), text_.size(), font_descriptor_->GetDWriteTextFormat(),
max_width_, max_height_, &text_layout_));
}
std::shared_ptr<FontDescriptor> WinTextLayout::GetFont() {
return font_descriptor_;
}
void WinTextLayout::SetFont(std::shared_ptr<FontDescriptor> font) {
auto f = std::dynamic_pointer_cast<WinFontDescriptor>(font);
assert(f);
f.swap(font_descriptor_);
ThrowIfFailed(graph_manager_->GetDWriteFactory()->CreateTextLayout(
text_.c_str(), text_.size(), font_descriptor_->GetDWriteTextFormat(),
max_width_, max_height_, &text_layout_));
}
void WinTextLayout::SetMaxWidth(float max_width) {
max_width_ = max_width;
ThrowIfFailed(text_layout_->SetMaxWidth(max_width_));
}
void WinTextLayout::SetMaxHeight(float max_height) {
max_height_ = max_height;
ThrowIfFailed(text_layout_->SetMaxHeight(max_height_));
}
ui::Rect WinTextLayout::GetTextBounds() {
DWRITE_TEXT_METRICS metrics;
ThrowIfFailed(text_layout_->GetMetrics(&metrics));
return ui::Rect{metrics.left, metrics.top, metrics.width, metrics.height};
}
std::vector<ui::Rect> WinTextLayout::TextRangeRect(
const ui::TextRange& text_range) {
DWRITE_TEXT_METRICS text_metrics;
ThrowIfFailed(text_layout_->GetMetrics(&text_metrics));
const auto metrics_count =
text_metrics.lineCount * text_metrics.maxBidiReorderingDepth;
std::vector<DWRITE_HIT_TEST_METRICS> hit_test_metrics(metrics_count);
UINT32 actual_count;
text_layout_->HitTestTextRange(text_range.position, text_range.count, 0, 0,
hit_test_metrics.data(), metrics_count,
&actual_count);
hit_test_metrics.erase(hit_test_metrics.cbegin() + actual_count,
hit_test_metrics.cend());
std::vector<ui::Rect> result;
result.reserve(actual_count);
for (const auto& metrics : hit_test_metrics) {
result.push_back(ui::Rect{metrics.left, metrics.top,
metrics.left + metrics.width,
metrics.top + metrics.height});
}
return result;
}
} // namespace cru::platform::win
|