tray: Save icons on *nix platforms to PNG instead of BMP

PNG has better compatibility with certain desktops.

This requires the stb_image_write header for PNG writing functionality.
This commit is contained in:
Frank Praznik
2025-08-26 23:20:41 -04:00
committed by Sam Lantinga
parent 285df94623
commit a904af1b43
4 changed files with 1814 additions and 4 deletions

View File

@@ -22,6 +22,7 @@
#include "SDL_internal.h"
#include "../SDL_tray_utils.h"
#include "../../video/SDL_stb_c.h"
#include <dlfcn.h>
#include <errno.h>
@@ -184,7 +185,7 @@ static bool new_tmp_filename(SDL_Tray *tray)
{
static int count = 0;
int would_have_written = SDL_asprintf(&tray->icon_path, "%s/%d.bmp", tray->icon_dir, count++);
int would_have_written = SDL_asprintf(&tray->icon_path, "%s/%d.png", tray->icon_dir, count++);
if (would_have_written >= 0) {
return true;
@@ -289,7 +290,7 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
goto icon_dir_error;
}
SDL_SaveBMP(icon, tray->icon_path);
SDL_SavePNG(icon, tray->icon_path);
} else {
// allocate a dummy icon path
SDL_asprintf(&tray->icon_path, " ");
@@ -342,7 +343,7 @@ void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
/* AppIndicator caches the icon files; always change filename to avoid caching */
if (icon && new_tmp_filename(tray)) {
SDL_SaveBMP(icon, tray->icon_path);
SDL_SavePNG(icon, tray->icon_path);
app_indicator_set_icon(tray->indicator, tray->icon_path);
} else {
SDL_free(tray->icon_path);

View File

@@ -21,7 +21,7 @@
#include "SDL_internal.h"
#include "SDL_stb_c.h"
#include "SDL_surface_c.h"
// We currently only support JPEG, but we could add other image formats if we wanted
#ifdef SDL_HAVE_STB
@@ -59,6 +59,13 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#undef memcpy
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define STB_IMAGE_WRITE_STATIC
#define STBI_WRITE_NO_STDIO
#define STBIW_ASSERT SDL_assert
#include "stb_image_write.h"
#undef memset
#endif
@@ -119,3 +126,68 @@ bool SDL_ConvertPixels_STB(int width, int height,
return SDL_SetError("SDL not built with STB image support");
#endif
}
#ifdef SDL_HAVE_STB
static void SDL_STBWriteFunc(void *context, void *data, int size)
{
SDL_WriteIO(context, data, size);
}
#endif
bool SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio)
{
#ifdef SDL_HAVE_STB
bool retval = true;
// Make sure we have somewhere to save
if (!SDL_SurfaceValid(surface)) {
retval = SDL_InvalidParamError("surface");
goto done;
}
if (!dst) {
retval = SDL_InvalidParamError("dst");
goto done;
}
bool free_surface = false;
if (surface->format != SDL_PIXELFORMAT_ABGR8888) {
surface = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888);
if (!surface) {
retval = false;
goto done;
}
free_surface = true;
}
if (!stbi_write_png_to_func(SDL_STBWriteFunc, dst, surface->w, surface->h, 4, surface->pixels, surface->pitch)) {
retval = SDL_SetError("Failed to write PNG");
}
if (free_surface) {
SDL_DestroySurface(surface);
}
done:
if (dst && closeio) {
retval = SDL_CloseIO(dst);
}
return retval;
#else
return SDL_SetError("SDL not built with STB image write support");
#endif
}
bool SDL_SavePNG(SDL_Surface *surface, const char *file)
{
#ifdef SDL_HAVE_STB
SDL_IOStream *stream = SDL_IOFromFile(file, "wb");
if (!stream) {
return false;
}
return SDL_SavePNG_IO(surface, stream, true);
#else
return SDL_SetError("SDL not built with STB image write support");
#endif
}

View File

@@ -27,5 +27,7 @@
// Image conversion functions
extern bool SDL_ConvertPixels_STB(int width, int height, SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
extern bool SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio);
extern bool SDL_SavePNG(SDL_Surface *surface, const char *file);
#endif // SDL_stb_c_h_

1735
src/video/stb_image_write.h Normal file

File diff suppressed because it is too large Load Diff