diff options
author | Michael Lutz <michi@icosahedron.de> | 2021-12-31 00:36:20 +0100 |
---|---|---|
committer | Michael Lutz <michi@icosahedron.de> | 2022-01-01 12:19:30 +0100 |
commit | f40e82a19d9f902979377d913507990d9bcf5621 (patch) | |
tree | a377dd7defd4c98f95aa0b364cd7448bb8182a11 /src/video | |
parent | 80fc5fb46c306b23ef9fb4ffc3cf201133092b9d (diff) | |
download | openttd-f40e82a19d9f902979377d913507990d9bcf5621.tar.xz |
Fix #9743: [OSX] Don't try to render touchbar sprites with invalid zoom level.
Diffstat (limited to 'src/video')
-rw-r--r-- | src/video/cocoa/cocoa_wnd.h | 2 | ||||
-rw-r--r-- | src/video/cocoa/cocoa_wnd.mm | 71 |
2 files changed, 32 insertions, 41 deletions
diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index d0c946067..6322bd171 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -90,8 +90,6 @@ static NSDictionary *touchBarFallbackText = @{ @interface OTTD_CocoaWindow : NSWindow #ifdef HAVE_TOUCHBAR_SUPPORT <NSTouchBarDelegate> - -- (NSImage *)generateImage:(int)spriteId; #endif - (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv; diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index b204fb440..355781d9e 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -132,6 +132,37 @@ static std::vector<WChar> NSStringToUTF32(NSString *s) return unicode_str; } +static void CGDataFreeCallback(void *, const void *data, size_t) +{ + delete[] (const uint32 *)data; +} + +/** + * Render an OTTD sprite to a Cocoa image. + * @param sprite_id Sprite to make a NSImage from. + * @param zoom Zoom level to render the sprite in. + * @return Autorelease'd image or nullptr on any error. + */ +static NSImage *NSImageFromSprite(SpriteID sprite_id, ZoomLevel zoom) +{ + if (!SpriteExists(sprite_id)) return nullptr; + + /* Fetch the sprite and create a new bitmap */ + Dimension dim = GetSpriteSize(sprite_id, nullptr, zoom); + std::unique_ptr<uint32[]> buffer = DrawSpriteToRgbaBuffer(sprite_id, zoom); + if (!buffer) return nullptr; // failed to blit sprite or we're using an 8bpp blitter. + + CFAutoRelease<CGDataProvider> data(CGDataProviderCreateWithData(nullptr, buffer.release(), dim.width * dim.height * 4, &CGDataFreeCallback)); + if (!data) return nullptr; + + CGBitmapInfo info = kCGImageAlphaFirst | kCGBitmapByteOrder32Host; + CFAutoRelease<CGColorSpaceRef> color_space(CGColorSpaceCreateWithName(kCGColorSpaceSRGB)); + CFAutoRelease<CGImage> bitmap(CGImageCreate(dim.width, dim.height, 8, 32, dim.width * 4, color_space.get(), info, data.get(), nullptr, false, kCGRenderingIntentDefault)); + if (!bitmap) return nullptr; + + return [ [ [ NSImage alloc ] initWithCGImage:bitmap.get() size:NSZeroSize ] autorelease ]; +} + /** * The main class of the application, the application's delegate. @@ -433,48 +464,10 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel return bar; } --(NSImage *)generateImage:(int)spriteId -{ - if (!SpriteExists(spriteId)) { - return nullptr; - } - - /* Fetch the sprite and create a new bitmap */ - const Sprite *fullspr = GetSprite(spriteId, ST_NORMAL); - const std::unique_ptr<uint32[]> buffer = DrawSpriteToRgbaBuffer(spriteId); - if (!buffer) { - return nullptr; // failed to blit sprite or we're using an 8bpp blitter. - } - - NSBitmapImageRep *bitmap = [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes:nil pixelsWide:fullspr->width pixelsHigh:fullspr->height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace bytesPerRow:0 bitsPerPixel:0 ]; - - /* Copy the sprite to the NSBitmapImageRep image buffer */ - const Colour *src = (const Colour *)buffer.get(); - for (int y = 0; y < fullspr->height; y++) { - for (int x = 0; x < fullspr->width; x++) { - NSUInteger pixel[4]; - pixel[0] = src->r; - pixel[1] = src->g; - pixel[2] = src->b; - pixel[3] = src->a; - [ bitmap setPixel:pixel atX:x y:y ]; - - src += 1; - } - } - - /* Finally, convert the NSBitmapImageRep we created to a NSimage we can put on the button and clean up. */ - NSImage *outImage = [ [ NSImage alloc ] initWithSize:NSMakeSize(fullspr->width, fullspr->height) ]; - [ outImage addRepresentation:bitmap ]; - [ bitmap release ]; - - return outImage; -} - - (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { NSNumber *num = touchBarButtonSprites[identifier]; - NSImage *image = [ self generateImage:num.unsignedIntValue ]; + NSImage *image = NSImageFromSprite(num.unsignedIntValue, _settings_client.gui.zoom_min); NSButton *button; if (image != nil) { |