diff options
-rw-r--r-- | demos/input_method/main.cpp | 4 | ||||
-rw-r--r-- | include/cru/osx/graphics/quartz/Painter.hpp | 2 | ||||
-rw-r--r-- | include/cru/osx/graphics/quartz/TextLayout.hpp | 9 | ||||
-rw-r--r-- | src/osx/graphics/quartz/Font.cpp | 1 | ||||
-rw-r--r-- | src/osx/graphics/quartz/Painter.cpp | 29 | ||||
-rw-r--r-- | src/osx/graphics/quartz/TextLayout.cpp | 105 |
6 files changed, 118 insertions, 32 deletions
diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp index 170e6dec..dc2e0858 100644 --- a/demos/input_method/main.cpp +++ b/demos/input_method/main.cpp @@ -31,7 +31,7 @@ int main() { auto target_clause_brush = graphics_factory->CreateSolidColorBrush(); target_clause_brush->SetColor(colors::blue); - std::shared_ptr<IFont> font = graphics_factory->CreateFont(u"等线", 30); + std::shared_ptr<IFont> font = graphics_factory->CreateFont(u"Serif", 30); float window_width = 10000; @@ -53,7 +53,7 @@ int main() { window->PaintEvent()->AddHandler([&](auto) { auto painter = window->BeginPaint(); - painter->Clear(colors::blue); + painter->Clear(colors::white); painter->DrawText(Point{}, prompt_text_layout.get(), brush.get()); diff --git a/include/cru/osx/graphics/quartz/Painter.hpp b/include/cru/osx/graphics/quartz/Painter.hpp index ea64c3d5..60a660a0 100644 --- a/include/cru/osx/graphics/quartz/Painter.hpp +++ b/include/cru/osx/graphics/quartz/Painter.hpp @@ -62,5 +62,7 @@ class QuartzCGContextPainter : public OsxQuartzResource, Size size_; std::function<void(QuartzCGContextPainter*)> on_end_draw_; + + std::vector<Rect> clip_stack_; }; } // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/TextLayout.hpp b/include/cru/osx/graphics/quartz/TextLayout.hpp index dd170142..92e0c861 100644 --- a/include/cru/osx/graphics/quartz/TextLayout.hpp +++ b/include/cru/osx/graphics/quartz/TextLayout.hpp @@ -35,7 +35,10 @@ class OsxCTTextLayout : public OsxQuartzResource, public virtual ITextLayout { CTFrameRef GetCTFrameRef() const { return ct_frame_; } + CTFrameRef CreateFrameWithColor(const Color& color); + private: + void ReleaseResource(); void RecreateFrame(); private: @@ -45,10 +48,10 @@ class OsxCTTextLayout : public OsxQuartzResource, public virtual ITextLayout { std::shared_ptr<OsxCTFont> font_; String text_; - CFStringRef cf_text_; + CFAttributedStringRef cf_attributed_text_; - CTFramesetterRef ct_framesetter_; - CTFrameRef ct_frame_; + CTFramesetterRef ct_framesetter_ = nullptr; + CTFrameRef ct_frame_ = nullptr; int line_count_; std::vector<CGPoint> line_origins_; std::vector<CTLineRef> lines_; diff --git a/src/osx/graphics/quartz/Font.cpp b/src/osx/graphics/quartz/Font.cpp index 596489e4..72d6d56d 100644 --- a/src/osx/graphics/quartz/Font.cpp +++ b/src/osx/graphics/quartz/Font.cpp @@ -13,6 +13,7 @@ OsxCTFont::OsxCTFont(IGraphicsFactory* graphics_factory, const String& name, CFStringRef n = Convert(name); ct_font_ = CTFontCreateWithName(n, size, nullptr); + Ensures(ct_font_); CFRelease(n); } diff --git a/src/osx/graphics/quartz/Painter.cpp b/src/osx/graphics/quartz/Painter.cpp index 0dc9e786..3f859571 100644 --- a/src/osx/graphics/quartz/Painter.cpp +++ b/src/osx/graphics/quartz/Painter.cpp @@ -6,6 +6,7 @@ #include "cru/osx/graphics/quartz/Geometry.hpp" #include "cru/osx/graphics/quartz/TextLayout.hpp" #include "cru/platform/Check.hpp" +#include "cru/platform/Color.hpp" #include "cru/platform/Exception.hpp" #include "cru/platform/graphics/util/Painter.hpp" @@ -118,20 +119,38 @@ void QuartzCGContextPainter::DrawText(const Point& offset, Validate(); auto tl = CheckPlatform<OsxCTTextLayout>(text_layout, GetPlatformId()); - auto b = CheckPlatform<QuartzBrush>(brush, GetPlatformId()); + + Color color; + + if (auto b = dynamic_cast<QuartzSolidColorBrush*>(brush)) { + color = b->GetColor(); + } else { + color = colors::black; + } util::WithTransform(this, Matrix::Translation(offset), - [this, tl, b](IPainter*) { - CTFrameDraw(tl->GetCTFrameRef(), cg_context_); + [this, tl, color](IPainter*) { + auto frame = tl->CreateFrameWithColor(color); + Ensures(frame); + CTFrameDraw(frame, cg_context_); + CFRelease(frame); }); } void QuartzCGContextPainter::PushLayer(const Rect& bounds) { - // TODO: Implement this. + Validate(); + clip_stack_.push_back(bounds); + CGContextClipToRect(cg_context_, Convert(bounds)); } void QuartzCGContextPainter::PopLayer() { - // TODO: Implement this. + Validate(); + clip_stack_.pop_back(); + if (clip_stack_.empty()) { + CGContextResetClip(cg_context_); + } else { + CGContextClipToRect(cg_context_, Convert(clip_stack_.back())); + } } void QuartzCGContextPainter::EndDraw() { DoEndDraw(); } diff --git a/src/osx/graphics/quartz/TextLayout.cpp b/src/osx/graphics/quartz/TextLayout.cpp index 6c6644e5..d96cf025 100644 --- a/src/osx/graphics/quartz/TextLayout.cpp +++ b/src/osx/graphics/quartz/TextLayout.cpp @@ -18,40 +18,62 @@ OsxCTTextLayout::OsxCTTextLayout(IGraphicsFactory* graphics_factory, max_height_(0.f), font_(std::move(font)), text_(str) { - cf_text_ = Convert(str); + Expects(font_); + + CFStringRef s = Convert(text_); + CFDictionaryRef attributes = + CFDictionaryCreateMutable(nullptr, 0, nullptr, nullptr); + + Ensures(s); + Ensures(attributes); + + cf_attributed_text_ = CFAttributedStringCreate(nullptr, s, attributes); + Ensures(cf_attributed_text_); + + CFRelease(attributes); + CFRelease(s); RecreateFrame(); } -OsxCTTextLayout::~OsxCTTextLayout() {} +OsxCTTextLayout::~OsxCTTextLayout() { + ReleaseResource(); + CFRelease(cf_attributed_text_); +} void OsxCTTextLayout::SetFont(std::shared_ptr<IFont> font) { font_ = CheckPlatform<OsxCTFont>(font, GetPlatformId()); - CFRelease(ct_framesetter_); - CFRelease(ct_frame_); RecreateFrame(); } void OsxCTTextLayout::SetText(String new_text) { text_ = std::move(new_text); - CFRelease(cf_text_); - cf_text_ = Convert(text_); - CFRelease(ct_framesetter_); - CFRelease(ct_frame_); + + CFRelease(cf_attributed_text_); + + CFStringRef s = Convert(text_); + CFDictionaryRef attributes = + CFDictionaryCreateMutable(nullptr, 0, nullptr, nullptr); + + Ensures(s); + Ensures(attributes); + + cf_attributed_text_ = CFAttributedStringCreate(nullptr, s, attributes); + Ensures(cf_attributed_text_); + + CFRelease(attributes); + CFRelease(s); + RecreateFrame(); } void OsxCTTextLayout::SetMaxWidth(float max_width) { max_width_ = max_width; - CFRelease(ct_framesetter_); - CFRelease(ct_frame_); RecreateFrame(); } void OsxCTTextLayout::SetMaxHeight(float max_height) { max_height_ = max_height; - CFRelease(ct_framesetter_); - CFRelease(ct_frame_); RecreateFrame(); } @@ -147,24 +169,38 @@ TextHitTestResult OsxCTTextLayout::HitTest(const Point& point) { return TextHitTestResult{0, false, false}; } +void OsxCTTextLayout::ReleaseResource() { + line_count_ = 0; + line_origins_.clear(); + lines_.clear(); + if (ct_framesetter_) CFRelease(ct_framesetter_); + if (ct_frame_) CFRelease(ct_frame_); +} + void OsxCTTextLayout::RecreateFrame() { - auto attributed_string = CFAttributedStringCreateMutable(nullptr, 0); - CFAttributedStringReplaceString(attributed_string, CFRangeMake(0, 0), - cf_text_); - CFAttributedStringSetAttribute(attributed_string, - CFRangeMake(0, CFStringGetLength(cf_text_)), - kCTFontAttributeName, font_->GetCTFont()); - ct_framesetter_ = CTFramesetterCreateWithAttributedString(attributed_string); + ReleaseResource(); + + ct_framesetter_ = + CTFramesetterCreateWithAttributedString(cf_attributed_text_); + Ensures(ct_framesetter_); auto path = CGPathCreateMutable(); + Ensures(path); CGPathAddRect(path, nullptr, CGRectMake(0, 0, max_width_, max_height_)); + CFMutableDictionaryRef dictionary = + CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(dictionary, kCTFontAttributeName, font_->GetCTFont()); + ct_frame_ = CTFramesetterCreateFrame( - ct_framesetter_, CFRangeMake(0, CFStringGetLength(cf_text_)), path, - nullptr); + ct_framesetter_, + CFRangeMake(0, CFAttributedStringGetLength(cf_attributed_text_)), path, + dictionary); + Ensures(ct_frame_); - CFRelease(attributed_string); CGPathRelease(path); + CFRelease(dictionary); const auto lines = CTFrameGetLines(ct_frame_); line_count_ = CFArrayGetCount(lines); @@ -176,4 +212,29 @@ void OsxCTTextLayout::RecreateFrame() { } } +CTFrameRef OsxCTTextLayout::CreateFrameWithColor(const Color& color) { + auto path = CGPathCreateMutable(); + CGPathAddRect(path, nullptr, CGRectMake(0, 0, max_width_, max_height_)); + + CFMutableDictionaryRef dictionary = + CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(dictionary, kCTFontAttributeName, font_->GetCTFont()); + + CGColorRef cg_color = + CGColorCreateGenericRGB(color.GetFloatRed(), color.GetFloatGreen(), + color.GetFloatBlue(), color.GetFloatAlpha()); + CFDictionaryAddValue(dictionary, kCTForegroundColorAttributeName, cg_color); + + auto frame = CTFramesetterCreateFrame( + ct_framesetter_, + CFRangeMake(0, CFAttributedStringGetLength(cf_attributed_text_)), path, + dictionary); + Ensures(frame); + + CGPathRelease(path); + CFRelease(dictionary); + + return frame; +} } // namespace cru::platform::graphics::osx::quartz |