From 10162b79fc8e34e8a82995c233933cbc63a11b44 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 27 Nov 2015 00:06:25 +0100 Subject: [PATCH] Handle pattern colours in wxColour ctor from NSColor Some colours returned in wxSystemSettingsNative::GetColour() can't be represented in RGBA color space as they use patterns, which explained why the compilation fix for 10.7 SDK in 56ebe6dfacaffac11e2f434c7653c8e09408b922 resulted in run-time crashes. Add code to support converting such NSColor objects to CGColorRef via NSImage, CGImageRef and CGPatternRef to make things really work. See #17141 --- src/osx/cocoa/colour.mm | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/osx/cocoa/colour.mm b/src/osx/cocoa/colour.mm index b47293b692..aca75b9174 100644 --- a/src/osx/cocoa/colour.mm +++ b/src/osx/cocoa/colour.mm @@ -34,6 +34,68 @@ wxColour::wxColour(WX_NSColor col) return; } + // Some colours use patterns, we can handle them with the help of CGColorRef + if ( NSColor* colPat = [col colorUsingColorSpaceName:NSPatternColorSpace] ) + { + NSImage* const nsimage = [colPat patternImage]; + if ( nsimage ) + { + NSSize size = [nsimage size]; + NSRect r = NSMakeRect(0, 0, size.width, size.height); + CGImageRef cgimage = [nsimage CGImageForProposedRect:&r context:nil hints:nil]; + if ( cgimage ) + { + // Callbacks for CGPatternCreate() + struct PatternCreateCallbacks + { + static void Draw(void *info, CGContextRef ctx) + { + CGImageRef image = (CGImageRef) info; + CGContextDrawImage + ( + ctx, + CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), + image + ); + } + + static void Release(void * WXUNUSED(info)) + { + // Do not release the image here, we don't own it as it + // comes from NSImage. + } + }; + + const CGPatternCallbacks callbacks = + { + /* version: */ 0, + &PatternCreateCallbacks::Draw, + &PatternCreateCallbacks::Release + }; + + CGPatternRef pattern = CGPatternCreate + ( + cgimage, + CGRectMake(0, 0, size.width, size.height), + CGAffineTransformMake(1, 0, 0, 1, 0, 0), + size.width, + size.height, + kCGPatternTilingConstantSpacing, + /* isColored: */ true, + &callbacks + ); + CGColorSpaceRef space = CGColorSpaceCreatePattern(NULL); + CGFloat components[1] = { 1.0 }; + CGColorRef cgcolor = CGColorCreateWithPattern(space, pattern, components); + CGColorSpaceRelease(space); + CGPatternRelease(pattern); + + InitCGColorRef(cgcolor); + return; + } + } + } + // Don't assert here, this will more likely than not result in a crash as // colours are often created in drawing code which will be called again // when the assert dialog is shown, resulting in a recursive assertion