diff options
Diffstat (limited to 'src/osx')
-rw-r--r-- | src/osx/graphics/quartz/Painter.cpp | 11 | ||||
-rw-r--r-- | src/osx/graphics/quartz/TextLayout.cpp | 171 | ||||
-rw-r--r-- | src/osx/gui/Window.mm | 15 |
3 files changed, 111 insertions, 86 deletions
diff --git a/src/osx/graphics/quartz/Painter.cpp b/src/osx/graphics/quartz/Painter.cpp index 5657e048..798e1256 100644 --- a/src/osx/graphics/quartz/Painter.cpp +++ b/src/osx/graphics/quartz/Painter.cpp @@ -158,16 +158,7 @@ void QuartzCGContextPainter::DrawText(const Point& offset, color = colors::black; } - auto bounds = tl->GetTextBounds(); - - bounds.width += bounds.left; - bounds.height += bounds.top; - bounds.left = bounds.top = 0; - - Matrix transform = - Matrix::Translation(-bounds.width / 2, -bounds.height / 2) * - Matrix::Scale(1, -1) * - Matrix::Translation(bounds.width / 2, bounds.height / 2); + Matrix transform = tl->GetTransform(); CGContextSaveGState(cg_context_); diff --git a/src/osx/graphics/quartz/TextLayout.cpp b/src/osx/graphics/quartz/TextLayout.cpp index 5145f9f9..d30c386f 100644 --- a/src/osx/graphics/quartz/TextLayout.cpp +++ b/src/osx/graphics/quartz/TextLayout.cpp @@ -72,83 +72,21 @@ void OsxCTTextLayout::SetMaxHeight(float max_height) { } Rect OsxCTTextLayout::GetTextBounds(bool includingTrailingSpace) { - float left = std::numeric_limits<float>::max(); - float top = std::numeric_limits<float>::max(); - float right = 0; - float bottom = 0; - - for (int i = 0; i < line_count_; i++) { - auto line = lines_[i]; - const auto& line_origin = line_origins_[i]; - - CGRect line_rect = CTLineGetImageBounds(line, nullptr); - if (includingTrailingSpace) { - float trailingWidth = CTLineGetTrailingWhitespaceWidth(line); - line_rect.size.width += trailingWidth; - } - - line_rect.origin.x += line_origin.x; - line_rect.origin.y += line_origin.y; - - left = std::min<float>(line_rect.origin.x, left); - top = std::min<float>(line_rect.origin.y, top); - right = std::max<float>(line_rect.origin.x + line_rect.size.width, right); - bottom = - std::max<float>(line_rect.origin.y + line_rect.size.height, bottom); - } - - return Rect::FromVertices(left, top, right, bottom); + return transform_.TransformRect(DoGetTextBounds(includingTrailingSpace)); } std::vector<Rect> OsxCTTextLayout::TextRangeRect(const TextRange& text_range) { - const auto r = text_.RangeFromCodeUnitToCodePoint(text_range).Normalize(); + std::vector<Rect> results = DoTextRangeRect(text_range); - std::vector<Rect> results; - - for (int i = 0; i < line_count_; i++) { - auto line = lines_[i]; - const auto& line_origin = line_origins_[i]; - - Range range = Convert(CTLineGetStringRange(line)); - range = range.CoerceInto(r.GetStart(), r.GetEnd()); - - if (range.count) { - auto line_rect = CTLineGetImageBounds(line, nullptr); - line_rect.origin.x += line_origin.x; - line_rect.origin.y += line_origin.y; - float start_offset = - CTLineGetOffsetForStringIndex(line, range.GetStart(), nullptr); - float end_offset = - CTLineGetOffsetForStringIndex(line, range.GetEnd(), nullptr); - line_rect.origin.x += start_offset; - line_rect.size.width = end_offset - start_offset; - results.push_back(Convert(line_rect)); - } + for (auto& rect : results) { + rect = transform_.TransformRect(rect); } return results; } -Point OsxCTTextLayout::TextSinglePoint(Index position, bool trailing) { - position = text_.IndexFromCodeUnitToCodePoint(position); - for (int i = 0; i < line_count_; i++) { - auto line = lines_[i]; - const auto& line_origin = line_origins_[i]; - - Range range = Convert(CTLineGetStringRange(line)); - if (range.GetStart() <= position && position < range.GetEnd()) { - auto offset = CTLineGetOffsetForStringIndex(line, position, nullptr); - return Point(line_origin.x + offset, line_origin.y); - } else if (position == range.GetEnd()) { - return Point( - line_origin.x + CTLineGetImageBounds(line, nullptr).size.width, - line_origin.y); - } - } - - if (lines_.empty()) return Point{}; - - return Convert(CTLineGetImageBounds(lines_.back(), nullptr)).GetRightTop(); +Rect OsxCTTextLayout::TextSinglePoint(Index position, bool trailing) { + return transform_.TransformRect(DoTextSinglePoint(position, trailing)); } TextHitTestResult OsxCTTextLayout::HitTest(const Point& point) { @@ -213,6 +151,13 @@ void OsxCTTextLayout::RecreateFrame() { for (int i = 0; i < line_count_; i++) { lines_[i] = static_cast<CTLineRef>(CFArrayGetValueAtIndex(lines, i)); } + + auto bounds = DoGetTextBounds(false); + + transform_ = + Matrix::Translation(-bounds.GetRight() / 2, -bounds.GetBottom() / 2) * + Matrix::Scale(1, -1) * + Matrix::Translation(bounds.GetRight() / 2, bounds.GetBottom() / 2); } CTFrameRef OsxCTTextLayout::CreateFrameWithColor(const Color& color) { @@ -243,4 +188,94 @@ String OsxCTTextLayout::GetDebugString() { max_height_); } +Rect OsxCTTextLayout::DoGetTextBounds(bool includingTrailingSpace) { + if (text_.empty()) return Rect{}; + + float left = std::numeric_limits<float>::max(); + float top = std::numeric_limits<float>::max(); + float right = 0; + float bottom = 0; + + for (int i = 0; i < line_count_; i++) { + auto line = lines_[i]; + const auto& line_origin = line_origins_[i]; + + CGRect line_rect = CTLineGetImageBounds(line, nullptr); + if (includingTrailingSpace) { + float trailingWidth = CTLineGetTrailingWhitespaceWidth(line); + line_rect.size.width += trailingWidth; + } + + line_rect.origin.x += line_origin.x; + line_rect.origin.y += line_origin.y; + + left = std::min<float>(line_rect.origin.x, left); + top = std::min<float>(line_rect.origin.y, top); + right = std::max<float>(line_rect.origin.x + line_rect.size.width, right); + bottom = + std::max<float>(line_rect.origin.y + line_rect.size.height, bottom); + } + + return Rect::FromVertices(left, top, right, bottom); +} + +std::vector<Rect> OsxCTTextLayout::DoTextRangeRect( + const TextRange& text_range) { + const auto r = text_.RangeFromCodeUnitToCodePoint(text_range).Normalize(); + + std::vector<Rect> results; + + for (int i = 0; i < line_count_; i++) { + auto line = lines_[i]; + const auto& line_origin = line_origins_[i]; + + Range range = Convert(CTLineGetStringRange(line)); + range = range.CoerceInto(r.GetStart(), r.GetEnd()); + + if (range.count) { + auto line_rect = CTLineGetImageBounds(line, nullptr); + line_rect.origin.x += line_origin.x; + line_rect.origin.y += line_origin.y; + float start_offset = + CTLineGetOffsetForStringIndex(line, range.GetStart(), nullptr); + float end_offset = + CTLineGetOffsetForStringIndex(line, range.GetEnd(), nullptr); + line_rect.origin.x += start_offset; + line_rect.size.width = end_offset - start_offset; + results.push_back(Convert(line_rect)); + } + } + + return results; +} + +Rect OsxCTTextLayout::DoTextSinglePoint(Index position, bool trailing) { + if (lines_.empty()) return Rect{0, 0, 0, font_->GetFontSize()}; + + position = text_.IndexFromCodeUnitToCodePoint(position); + for (int i = 0; i < line_count_; i++) { + auto line = lines_[i]; + const auto& line_origin = line_origins_[i]; + + auto rect = Convert(CTLineGetImageBounds(line, nullptr)); + rect.left += line_origin.x; + rect.top += line_origin.y; + + Range range = Convert(CTLineGetStringRange(line)); + if (range.GetStart() <= position && position < range.GetEnd()) { + auto offset = CTLineGetOffsetForStringIndex(line, position, nullptr); + return Rect(rect.left + offset, rect.top, 0, rect.height); + } else if (position == range.GetEnd()) { + return Rect(rect.GetRight(), rect.top, 0, rect.height); + } + } + + // TODO: Complete logic here. + + auto rect = Convert(CTLineGetImageBounds(lines_.back(), nullptr)); + rect.left = rect.GetRight(); + rect.width = 0; + return rect; +} + } // namespace cru::platform::graphics::osx::quartz diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm index 9a71d271..356c6be6 100644 --- a/src/osx/gui/Window.mm +++ b/src/osx/gui/Window.mm @@ -27,7 +27,6 @@ #include <Foundation/NSAttributedString.h> #include <Foundation/NSString.h> -#include <gsl/gsl_assert> #include <limits> #include <memory> #include <unordered_set> @@ -496,11 +495,11 @@ const std::unordered_set<KeyCode> bypass_codes{ auto ss = Convert(s); - cru::log::TagDebug(u"CruView", - u"Received setMarkedText string: {}, selected range: ({}, {}), " - u"replacement range: ({}, {}).", - ss, selectedRange.location, selectedRange.length, replacementRange.location, - replacementRange.length); + // cru::log::TagDebug(u"CruView", + // u"Received setMarkedText string: {}, selected range: ({}, {}), " + // u"replacement range: ({}, {}).", + // ss, selectedRange.location, selectedRange.length, replacementRange.location, + // replacementRange.length); if (_input_context_text == nil) { _input_context_text = [[NSMutableAttributedString alloc] init]; @@ -557,8 +556,8 @@ const std::unordered_set<KeyCode> bypass_codes{ _input_context_p->SetCompositionText(cru::platform::gui::CompositionText()); cru::String ss = Convert(s); - cru::log::TagDebug(u"CruView", u"Finish composition: {}, replacement range: ({}, {})", ss, - replacementRange.location, replacementRange.length); + // cru::log::TagDebug(u"CruView", u"Finish composition: {}, replacement range: ({}, {})", ss, + // replacementRange.location, replacementRange.length); _input_context_p->RaiseCompositionEvent(); _input_context_p->RaiseCompositionEndEvent(); |