diff options
-rw-r--r-- | demos/input_method/main.cpp | 49 | ||||
-rw-r--r-- | include/cru/platform/graph/text_layout.hpp | 2 | ||||
-rw-r--r-- | include/cru/platform/graph_base.hpp | 5 | ||||
-rw-r--r-- | include/cru/win/graph/direct/text_layout.hpp | 2 | ||||
-rw-r--r-- | src/win/graph/direct/text_layout.cpp | 2 |
5 files changed, 37 insertions, 23 deletions
diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp index ce96a8c1..ebca7a9d 100644 --- a/demos/input_method/main.cpp +++ b/demos/input_method/main.cpp @@ -33,6 +33,8 @@ int main() { std::shared_ptr<IFont> font = graph_factory->CreateFont("等线", 30); + float window_width = 10000; + auto prompt_text_layout = graph_factory->CreateTextLayout(font, "Alt+F1: Enable IME\n" @@ -40,29 +42,35 @@ int main() { "Alt+F3: Complete composition.\n" "Alt+F4: Cancel composition."); - auto no_composition_text_layout = - graph_factory->CreateTextLayout(font, "Not compositioning!"); - std::optional<CompositionText> optional_composition_text; std::string committed_text; + window->ResizeEvent()->AddHandler( + [&prompt_text_layout, &window_width](const Size& size) { + prompt_text_layout->SetMaxWidth(size.width); + window_width = size.width; + }); + window->PaintEvent()->AddHandler([&](auto) { auto painter = window->BeginPaint(); painter->Clear(colors::white); painter->DrawText(Point{}, prompt_text_layout.get(), brush.get()); - auto anchor_y = prompt_text_layout->GetTextBounds().height; + const auto anchor_y = prompt_text_layout->GetTextBounds().height; + + auto text_layout = graph_factory->CreateTextLayout( + font, + committed_text + + (optional_composition_text ? optional_composition_text->text : "")); if (optional_composition_text) { const auto& composition_text = *optional_composition_text; - auto composition_text_layout = - graph_factory->CreateTextLayout(font, composition_text.text); for (int i = 0; i < composition_text.clauses.size(); i++) { const auto& clause = composition_text.clauses[i]; - auto rects = composition_text_layout->TextRangeRect( - TextRange::FromTwoSides(clause.start, clause.end)); + auto rects = text_layout->TextRangeRect(TextRange::FromTwoSides( + clause.start, clause.end, committed_text.size())); const auto& b = clause.target ? target_clause_brush : (i % 2 ? odd_clause_brush : even_clause_brush); @@ -71,22 +79,23 @@ int main() { painter->FillRectangle(rect, b.get()); } } + } - painter->DrawText(Point{0, anchor_y}, composition_text_layout.get(), - brush.get()); + painter->DrawText(Point{0, anchor_y}, text_layout.get(), brush.get()); - anchor_y += composition_text_layout->GetTextBounds().height; - } else { - painter->DrawText(Point{0, anchor_y}, no_composition_text_layout.get(), - brush.get()); - anchor_y += no_composition_text_layout->GetTextBounds().height; - } + if (optional_composition_text) { + const auto& composition_text = *optional_composition_text; - auto committed_text_layout = - graph_factory->CreateTextLayout(font, committed_text); + const auto cursor_pos = composition_text.selection.position + + gsl::narrow_cast<int>(committed_text.size()); - painter->DrawText(Point{0, anchor_y}, committed_text_layout.get(), - brush.get()); + const auto cursor_lefttop = + text_layout->TextSingleRect(cursor_pos, false); + + painter->FillRectangle(Rect{cursor_lefttop.x, cursor_lefttop.y + anchor_y, + 3, font->GetFontSize()}, + brush.get()); + } }); window->KeyDownEvent()->AddHandler( diff --git a/include/cru/platform/graph/text_layout.hpp b/include/cru/platform/graph/text_layout.hpp index 20009c0d..0d104742 100644 --- a/include/cru/platform/graph/text_layout.hpp +++ b/include/cru/platform/graph/text_layout.hpp @@ -17,7 +17,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 Point TextSingleRect(gsl::index position, bool trailing) = 0; virtual TextHitTestResult HitTest(const Point& point) = 0; }; } // namespace cru::platform::graph diff --git a/include/cru/platform/graph_base.hpp b/include/cru/platform/graph_base.hpp index f25a7baf..0b997770 100644 --- a/include/cru/platform/graph_base.hpp +++ b/include/cru/platform/graph_base.hpp @@ -218,6 +218,11 @@ struct TextRange final { return TextRange(start, end - start); } + constexpr static TextRange FromTwoSides(gsl::index start, gsl::index end, + gsl::index offset) { + return TextRange(start + offset, end - start); + } + constexpr TextRange() = default; constexpr TextRange(const gsl::index position, const gsl::index count = 0) : position(position), count(count) {} diff --git a/include/cru/win/graph/direct/text_layout.hpp b/include/cru/win/graph/direct/text_layout.hpp index 462a5fd3..a9b89011 100644 --- a/include/cru/win/graph/direct/text_layout.hpp +++ b/include/cru/win/graph/direct/text_layout.hpp @@ -38,7 +38,7 @@ class DWriteTextLayout : public DirectGraphResource, Rect GetTextBounds() override; std::vector<Rect> TextRangeRect(const TextRange& text_range) override; - Point TextSingleRect(int position, bool trailing) override; + Point TextSingleRect(gsl::index position, bool trailing) override; TextHitTestResult HitTest(const Point& point) override; private: diff --git a/src/win/graph/direct/text_layout.cpp b/src/win/graph/direct/text_layout.cpp index 6a6a2c45..f582dd0a 100644 --- a/src/win/graph/direct/text_layout.cpp +++ b/src/win/graph/direct/text_layout.cpp @@ -99,7 +99,7 @@ std::vector<Rect> DWriteTextLayout::TextRangeRect(const TextRange& text_range) { return result; } -Point DWriteTextLayout::TextSingleRect(int position, bool trailing) { +Point DWriteTextLayout::TextSingleRect(gsl::index position, bool trailing) { const auto index = IndexUtf8ToUtf16(text_, static_cast<int>(position), w_text_); |