From 393b57511c5d045bb8246f6ef6be7cdcab180c2b Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Thu, 9 Feb 2023 18:23:14 +0100 Subject: [PATCH] Respect composition mode in wxOSX wxGraphicsContext::DrawBitmap() Pass the current composition mode to wxOSXDrawNSImage() instead of always using NSCompositeSourceOver in it. See #23240, #23245. (cherry picked from commit e269245b97ced95f60b11fb7ea988a3f7a993e7f with some extra changes for ABI compatibility in 3.2) --- docs/changes.txt | 4 ++ include/wx/osx/cocoa/private.h | 7 ++++ src/osx/carbon/graphics.cpp | 4 +- src/osx/carbon/utilscocoa.mm | 75 ++++++++++++++++++++++++++++++++-- 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index ca3725c37e..6be424f3f1 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -239,6 +239,10 @@ All: - Add move ctor and assignment to wxString (Pavel Tyunin, #23224). +wxOSX: + +- Respect composition mode when drawing bitmaps (#23240). + 3.2.2: (released 2023-02-08) ---------------------------- diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index b0d9f2f4c2..ceb7050a76 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -34,10 +34,17 @@ OSStatus WXDLLIMPEXP_CORE wxMacDrawCGImage( CGContextRef inContext, const CGRect * inBounds, CGImageRef inImage) ; + void WXDLLIMPEXP_CORE wxOSXDrawNSImage( CGContextRef inContext, const CGRect * inBounds, WX_NSImage inImage) ; + +void WXDLLIMPEXP_CORE wxOSXDrawNSImage( + CGContextRef inContext, + const CGRect * inBounds, + WX_NSImage inImage, + wxCompositionMode composition) ; WX_NSImage WXDLLIMPEXP_CORE wxOSXGetSystemImage(const wxString& name); WX_NSImage WXDLLIMPEXP_CORE wxOSXGetNSImageFromCGImage( CGImageRef image, double scale = 1.0, bool isTemplate = false); WX_NSImage WXDLLIMPEXP_CORE wxOSXGetNSImageFromIconRef( WXHICON iconref ); diff --git a/src/osx/carbon/graphics.cpp b/src/osx/carbon/graphics.cpp index 6fb3229d56..7b22a1bbd3 100644 --- a/src/osx/carbon/graphics.cpp +++ b/src/osx/carbon/graphics.cpp @@ -2427,7 +2427,7 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDo if (EnsureIsValid()) { CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h ); - wxOSXDrawNSImage( m_cgContext, &r, bmp.GetNSImage()); + wxOSXDrawNSImage( m_cgContext, &r, bmp.GetNSImage(), m_composition); } #else wxGraphicsBitmap bitmap = GetRenderer()->CreateBitmap(bmp); @@ -2490,7 +2490,7 @@ void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDoubl #if wxOSX_USE_COCOA { CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h ); - wxOSXDrawNSImage( m_cgContext, &r, icon.GetNSImage()); + wxOSXDrawNSImage( m_cgContext, &r, icon.GetNSImage(), m_composition); } #endif diff --git a/src/osx/carbon/utilscocoa.mm b/src/osx/carbon/utilscocoa.mm index 4dbf4848e8..1ba31461cf 100644 --- a/src/osx/carbon/utilscocoa.mm +++ b/src/osx/carbon/utilscocoa.mm @@ -287,10 +287,78 @@ CGContextRef WXDLLIMPEXP_CORE wxOSXCreateBitmapContextFromImage( WXImage nsimage return hbitmap; } +namespace +{ +#if wxOSX_USE_COCOA + NSCompositingOperation wxOSXNSCompositionFromWXComposition( wxCompositionMode composition ) + { + NSCompositingOperation mode = NSCompositingOperationSourceOver; + switch( composition ) + { + case wxCOMPOSITION_CLEAR: + mode = NSCompositingOperationClear; + break; + case wxCOMPOSITION_SOURCE: + mode = NSCompositingOperationCopy; + break; + case wxCOMPOSITION_OVER: + mode = NSCompositingOperationSourceOver; + break; + case wxCOMPOSITION_IN: + mode = NSCompositingOperationSourceIn; + break; + case wxCOMPOSITION_OUT: + mode = NSCompositingOperationSourceOut; + break; + case wxCOMPOSITION_ATOP: + mode = NSCompositingOperationSourceAtop; + break; + case wxCOMPOSITION_DEST_OVER: + mode = NSCompositingOperationDestinationOver; + break; + case wxCOMPOSITION_DEST_IN: + mode = NSCompositingOperationDestinationIn; + break; + case wxCOMPOSITION_DEST_OUT: + mode = NSCompositingOperationDestinationOut; + break; + case wxCOMPOSITION_DEST_ATOP: + mode = NSCompositingOperationDestinationAtop; + break; + case wxCOMPOSITION_XOR: + mode = NSCompositingOperationExclusion; // Not NSCompositingOperationXOR! + break; + case wxCOMPOSITION_ADD: + mode = NSCompositingOperationPlusLighter ; + break; + case wxCOMPOSITION_DIFF: + mode = NSCompositingOperationDifference ; + break; + default: + mode = NSCompositingOperationSourceOver; + break; + } + + return mode; + } +#endif +} // anonymous namespace + +#if wxOSX_USE_COCOA void WXDLLIMPEXP_CORE wxOSXDrawNSImage( CGContextRef inContext, const CGRect * inBounds, WXImage inImage) +{ + wxOSXDrawNSImage(inContext, inBounds, inImage, wxCOMPOSITION_OVER); +} +#endif + +void WXDLLIMPEXP_CORE wxOSXDrawNSImage( + CGContextRef inContext, + const CGRect * inBounds, + WXImage inImage, + wxCompositionMode composition) { if (inImage != nil) { @@ -301,13 +369,14 @@ void WXDLLIMPEXP_CORE wxOSXDrawNSImage( CGContextScaleCTM(inContext, 1, -1); #if wxOSX_USE_COCOA - NSGraphicsContext *previousContext = [NSGraphicsContext currentContext]; + NSGraphicsContext *previousContext = [NSGraphicsContext currentContext]; NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext graphicsContextWithCGContext:inContext flipped:NO]; [NSGraphicsContext setCurrentContext:nsGraphicsContext]; - [inImage drawInRect:NSRectFromCGRect(r) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; + + [inImage drawInRect:NSRectFromCGRect(r) fromRect:NSZeroRect operation:wxOSXNSCompositionFromWXComposition(composition) fraction:1.0]; [NSGraphicsContext setCurrentContext:previousContext]; #else - CGContextDrawImage(inContext, *inBounds, [inImage CGImage]); + CGContextDrawImage(inContext, r, [inImage CGImage]); #endif CGContextRestoreGState(inContext);