From 74aee8a6308445604b513ab37812ddc99365aa98 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 9 Sep 2021 17:55:40 +0800 Subject: ... --- src/osx/graphics/quartz/TextLayout.cpp | 66 +++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) (limited to 'src/osx/graphics/quartz/TextLayout.cpp') diff --git a/src/osx/graphics/quartz/TextLayout.cpp b/src/osx/graphics/quartz/TextLayout.cpp index 08495634..73bfb1ce 100644 --- a/src/osx/graphics/quartz/TextLayout.cpp +++ b/src/osx/graphics/quartz/TextLayout.cpp @@ -3,6 +3,9 @@ #include "cru/osx/graphics/quartz/Resource.hpp" #include "cru/platform/Check.hpp" +#include +#include + namespace cru::platform::graphics::osx::quartz { OsxCTTextLayout::OsxCTTextLayout(IGraphFactory* graphics_factory, std::shared_ptr font, @@ -48,15 +51,59 @@ void OsxCTTextLayout::SetMaxHeight(float max_height) { } Rect OsxCTTextLayout::GetTextBounds(bool includingTrailingSpace) { - auto lines = CTFrameGetLines(ct_frame_); + float left = std::numeric_limits::max(); + float top = std::numeric_limits::max(); + float right = 0; + float bottom = 0; + + for (int i = 0; i < line_count_; i++) { + auto line = static_cast(lines_[i]); + const auto& line_origin = line_origins_[i]; - const auto line_count = CFArrayGetCount(lines); + CGRect line_rect = CTLineGetImageBounds(line, nullptr); + if (includingTrailingSpace) { + float trailingWidth = CTLineGetTrailingWhitespaceWidth(line); + line_rect.size.width += trailingWidth; + } - for (int i = 0; i < line_count; i++) { - auto line = CFArrayGetValueAtIndex(lines, i); + line_rect.origin.x += line_origin.x; + line_rect.origin.y += line_origin.y; - // TODO: To be continued! + left = std::min(line_rect.origin.x, left); + top = std::min(line_rect.origin.y, top); + right = std::max(line_rect.origin.x + line_rect.size.width, right); + bottom = + std::max(line_rect.origin.y + line_rect.size.height, bottom); } + + return Rect::FromVertices(left, top, right, bottom); +} + +std::vector OsxCTTextLayout::TextRangeRect(const TextRange& text_range) { + const auto r = text_.RangeFromCodeUnitToCodePoint(text_range).Normalize(); + + std::vector 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; } void OsxCTTextLayout::RecreateFrame() { @@ -77,5 +124,14 @@ void OsxCTTextLayout::RecreateFrame() { CFRelease(attributed_string); CGPathRelease(path); + + const auto lines = CTFrameGetLines(ct_frame_); + line_count_ = CFArrayGetCount(lines); + lines_.resize(line_count_); + line_origins_.resize(line_count_); + CTFrameGetLineOrigins(ct_frame_, CFRangeMake(0, 0), line_origins_.data()); + for (int i = 0; i < line_count_; i++) { + lines_[i] = static_cast(CFArrayGetValueAtIndex(lines, i)); + } } } // namespace cru::platform::graphics::osx::quartz -- cgit v1.2.3