Browse Source

Merge pull request #92826 from bruvzg/nat_icon_checks

Improve native menu and status indicator icons conversion and checks.
Rémi Verschelde 1 year ago
parent
commit
a139cd611a

+ 8 - 66
platform/macos/display_server_macos.mm

@@ -3166,42 +3166,13 @@ void DisplayServerMacOS::set_icon(const Ref<Image> &p_icon) {
 
 DisplayServer::IndicatorID DisplayServerMacOS::create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) {
 	NSImage *nsimg = nullptr;
-	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
+	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 		Ref<Image> img = p_icon->get_image();
 		img = img->duplicate();
-		img->convert(Image::FORMAT_RGBA8);
-
-		NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
-				initWithBitmapDataPlanes:nullptr
-							  pixelsWide:img->get_width()
-							  pixelsHigh:img->get_height()
-						   bitsPerSample:8
-						 samplesPerPixel:4
-								hasAlpha:YES
-								isPlanar:NO
-						  colorSpaceName:NSDeviceRGBColorSpace
-							 bytesPerRow:img->get_width() * 4
-							bitsPerPixel:32];
-		if (imgrep) {
-			uint8_t *pixels = [imgrep bitmapData];
-
-			int len = img->get_width() * img->get_height();
-			const uint8_t *r = img->get_data().ptr();
-
-			/* Premultiply the alpha channel */
-			for (int i = 0; i < len; i++) {
-				uint8_t alpha = r[i * 4 + 3];
-				pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255);
-				pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255);
-				pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255);
-				pixels[i * 4 + 3] = alpha;
-			}
-
-			nsimg = [[NSImage alloc] initWithSize:NSMakeSize(img->get_width(), img->get_height())];
-			if (nsimg) {
-				[nsimg addRepresentation:imgrep];
-			}
+		if (img->is_compressed()) {
+			img->decompress();
 		}
+		nsimg = _convert_to_nsimg(img);
 	}
 
 	IndicatorData idat;
@@ -3229,42 +3200,13 @@ void DisplayServerMacOS::status_indicator_set_icon(IndicatorID p_id, const Ref<T
 	ERR_FAIL_COND(!indicators.has(p_id));
 
 	NSImage *nsimg = nullptr;
-	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
+	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 		Ref<Image> img = p_icon->get_image();
 		img = img->duplicate();
-		img->convert(Image::FORMAT_RGBA8);
-
-		NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
-				initWithBitmapDataPlanes:nullptr
-							  pixelsWide:img->get_width()
-							  pixelsHigh:img->get_height()
-						   bitsPerSample:8
-						 samplesPerPixel:4
-								hasAlpha:YES
-								isPlanar:NO
-						  colorSpaceName:NSDeviceRGBColorSpace
-							 bytesPerRow:img->get_width() * 4
-							bitsPerPixel:32];
-		if (imgrep) {
-			uint8_t *pixels = [imgrep bitmapData];
-
-			int len = img->get_width() * img->get_height();
-			const uint8_t *r = img->get_data().ptr();
-
-			/* Premultiply the alpha channel */
-			for (int i = 0; i < len; i++) {
-				uint8_t alpha = r[i * 4 + 3];
-				pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255);
-				pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255);
-				pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255);
-				pixels[i * 4 + 3] = alpha;
-			}
-
-			nsimg = [[NSImage alloc] initWithSize:NSMakeSize(img->get_width(), img->get_height())];
-			if (nsimg) {
-				[nsimg addRepresentation:imgrep];
-			}
+		if (img->is_compressed()) {
+			img->decompress();
 		}
+		nsimg = _convert_to_nsimg(img);
 	}
 
 	NSStatusItem *item = indicators[p_id].item;

+ 4 - 4
platform/macos/native_menu_macos.mm

@@ -461,7 +461,7 @@ int NativeMenuMacOS::add_icon_item(const RID &p_rid, const Ref<Texture2D> &p_ico
 		obj->max_states = 0;
 		obj->state = 0;
 		DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
-		if (ds && p_icon.is_valid()) {
+		if (ds && p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 			obj->img = p_icon->get_image();
 			obj->img = obj->img->duplicate();
 			if (obj->img->is_compressed()) {
@@ -492,7 +492,7 @@ int NativeMenuMacOS::add_icon_check_item(const RID &p_rid, const Ref<Texture2D>
 		obj->max_states = 0;
 		obj->state = 0;
 		DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
-		if (ds && p_icon.is_valid()) {
+		if (ds && p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 			obj->img = p_icon->get_image();
 			obj->img = obj->img->duplicate();
 			if (obj->img->is_compressed()) {
@@ -543,7 +543,7 @@ int NativeMenuMacOS::add_icon_radio_check_item(const RID &p_rid, const Ref<Textu
 		obj->max_states = 0;
 		obj->state = 0;
 		DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
-		if (ds && p_icon.is_valid()) {
+		if (ds && p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 			obj->img = p_icon->get_image();
 			obj->img = obj->img->duplicate();
 			if (obj->img->is_compressed()) {
@@ -1237,7 +1237,7 @@ void NativeMenuMacOS::set_item_icon(const RID &p_rid, int p_idx, const Ref<Textu
 		GodotMenuItem *obj = [menu_item representedObject];
 		ERR_FAIL_NULL(obj);
 		DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
-		if (ds && p_icon.is_valid()) {
+		if (ds && p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 			obj->img = p_icon->get_image();
 			obj->img = obj->img->duplicate();
 			if (obj->img->is_compressed()) {

+ 8 - 2
platform/windows/display_server_windows.cpp

@@ -3166,9 +3166,12 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
 
 DisplayServer::IndicatorID DisplayServerWindows::create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) {
 	HICON hicon = nullptr;
-	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
+	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 		Ref<Image> img = p_icon->get_image();
 		img = img->duplicate();
+		if (img->is_compressed()) {
+			img->decompress();
+		}
 		img->convert(Image::FORMAT_RGBA8);
 
 		int w = img->get_width();
@@ -3236,9 +3239,12 @@ void DisplayServerWindows::status_indicator_set_icon(IndicatorID p_id, const Ref
 	ERR_FAIL_COND(!indicators.has(p_id));
 
 	HICON hicon = nullptr;
-	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0) {
+	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 		Ref<Image> img = p_icon->get_image();
 		img = img->duplicate();
+		if (img->is_compressed()) {
+			img->decompress();
+		}
 		img->convert(Image::FORMAT_RGBA8);
 
 		int w = img->get_width();

+ 24 - 16
platform/windows/native_menu_windows.cpp

@@ -35,6 +35,8 @@
 #include "scene/resources/image_texture.h"
 
 HBITMAP NativeMenuWindows::_make_bitmap(const Ref<Image> &p_img) const {
+	p_img->convert(Image::FORMAT_RGBA8);
+
 	Vector2i texture_size = p_img->get_size();
 	UINT image_size = texture_size.width * texture_size.height;
 
@@ -354,12 +356,14 @@ int NativeMenuWindows::add_icon_item(const RID &p_rid, const Ref<Texture2D> &p_i
 	item_data->checkable_type = CHECKABLE_TYPE_NONE;
 	item_data->max_states = 0;
 	item_data->state = 0;
-	item_data->img = p_icon->get_image();
-	item_data->img = item_data->img->duplicate();
-	if (item_data->img->is_compressed()) {
-		item_data->img->decompress();
+	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
+		item_data->img = p_icon->get_image();
+		item_data->img = item_data->img->duplicate();
+		if (item_data->img->is_compressed()) {
+			item_data->img->decompress();
+		}
+		item_data->bmp = _make_bitmap(item_data->img);
 	}
-	item_data->bmp = _make_bitmap(item_data->img);
 
 	Char16String label = p_label.utf16();
 	MENUITEMINFOW item;
@@ -394,12 +398,14 @@ int NativeMenuWindows::add_icon_check_item(const RID &p_rid, const Ref<Texture2D
 	item_data->checkable_type = CHECKABLE_TYPE_CHECK_BOX;
 	item_data->max_states = 0;
 	item_data->state = 0;
-	item_data->img = p_icon->get_image();
-	item_data->img = item_data->img->duplicate();
-	if (item_data->img->is_compressed()) {
-		item_data->img->decompress();
+	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
+		item_data->img = p_icon->get_image();
+		item_data->img = item_data->img->duplicate();
+		if (item_data->img->is_compressed()) {
+			item_data->img->decompress();
+		}
+		item_data->bmp = _make_bitmap(item_data->img);
 	}
-	item_data->bmp = _make_bitmap(item_data->img);
 
 	Char16String label = p_label.utf16();
 	MENUITEMINFOW item;
@@ -467,12 +473,14 @@ int NativeMenuWindows::add_icon_radio_check_item(const RID &p_rid, const Ref<Tex
 	item_data->checkable_type = CHECKABLE_TYPE_RADIO_BUTTON;
 	item_data->max_states = 0;
 	item_data->state = 0;
-	item_data->img = p_icon->get_image();
-	item_data->img = item_data->img->duplicate();
-	if (item_data->img->is_compressed()) {
-		item_data->img->decompress();
+	if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
+		item_data->img = p_icon->get_image();
+		item_data->img = item_data->img->duplicate();
+		if (item_data->img->is_compressed()) {
+			item_data->img->decompress();
+		}
+		item_data->bmp = _make_bitmap(item_data->img);
 	}
-	item_data->bmp = _make_bitmap(item_data->img);
 
 	Char16String label = p_label.utf16();
 	MENUITEMINFOW item;
@@ -1087,7 +1095,7 @@ void NativeMenuWindows::set_item_icon(const RID &p_rid, int p_idx, const Ref<Tex
 			if (item_data->bmp) {
 				DeleteObject(item_data->bmp);
 			}
-			if (p_icon.is_valid()) {
+			if (p_icon.is_valid() && p_icon->get_width() > 0 && p_icon->get_height() > 0 && p_icon->get_image().is_valid()) {
 				item_data->img = p_icon->get_image();
 				item_data->img = item_data->img->duplicate();
 				if (item_data->img->is_compressed()) {