mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-02 06:12:08 +02:00
Added SDL_AddSurfaceAlternateImage(), SDL_SurfaceHasAlternateImages(), SDL_GetSurfaceImages() and SDL_RemoveSurfaceAlternateImages()
These functions allow you to create surfaces with alternate high DPI content, and will be used for high DPI icon and cursor support.
This commit is contained in:
@@ -8,6 +8,7 @@ SDL3_0.0.0 {
|
||||
SDL_AddGamepadMappingsFromFile;
|
||||
SDL_AddGamepadMappingsFromIO;
|
||||
SDL_AddHintCallback;
|
||||
SDL_AddSurfaceAlternateImage;
|
||||
SDL_AddTimer;
|
||||
SDL_AddTimerNS;
|
||||
SDL_AddVulkanRenderSemaphores;
|
||||
@@ -438,6 +439,7 @@ SDL3_0.0.0 {
|
||||
SDL_GetSurfaceColorKey;
|
||||
SDL_GetSurfaceColorMod;
|
||||
SDL_GetSurfaceColorspace;
|
||||
SDL_GetSurfaceImages;
|
||||
SDL_GetSurfacePalette;
|
||||
SDL_GetSurfaceProperties;
|
||||
SDL_GetSystemRAM;
|
||||
@@ -644,6 +646,7 @@ SDL3_0.0.0 {
|
||||
SDL_ReloadGamepadMappings;
|
||||
SDL_RemovePath;
|
||||
SDL_RemoveStoragePath;
|
||||
SDL_RemoveSurfaceAlternateImages;
|
||||
SDL_RemoveTimer;
|
||||
SDL_RenamePath;
|
||||
SDL_RenameStoragePath;
|
||||
@@ -820,6 +823,7 @@ SDL3_0.0.0 {
|
||||
SDL_StopTextInput;
|
||||
SDL_StorageReady;
|
||||
SDL_StringToGUID;
|
||||
SDL_SurfaceHasAlternateImages;
|
||||
SDL_SurfaceHasColorKey;
|
||||
SDL_SurfaceHasRLE;
|
||||
SDL_SyncWindow;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#define SDL_AddGamepadMappingsFromFile SDL_AddGamepadMappingsFromFile_REAL
|
||||
#define SDL_AddGamepadMappingsFromIO SDL_AddGamepadMappingsFromIO_REAL
|
||||
#define SDL_AddHintCallback SDL_AddHintCallback_REAL
|
||||
#define SDL_AddSurfaceAlternateImage SDL_AddSurfaceAlternateImage_REAL
|
||||
#define SDL_AddTimer SDL_AddTimer_REAL
|
||||
#define SDL_AddTimerNS SDL_AddTimerNS_REAL
|
||||
#define SDL_AddVulkanRenderSemaphores SDL_AddVulkanRenderSemaphores_REAL
|
||||
@@ -463,6 +464,7 @@
|
||||
#define SDL_GetSurfaceColorKey SDL_GetSurfaceColorKey_REAL
|
||||
#define SDL_GetSurfaceColorMod SDL_GetSurfaceColorMod_REAL
|
||||
#define SDL_GetSurfaceColorspace SDL_GetSurfaceColorspace_REAL
|
||||
#define SDL_GetSurfaceImages SDL_GetSurfaceImages_REAL
|
||||
#define SDL_GetSurfacePalette SDL_GetSurfacePalette_REAL
|
||||
#define SDL_GetSurfaceProperties SDL_GetSurfaceProperties_REAL
|
||||
#define SDL_GetSystemRAM SDL_GetSystemRAM_REAL
|
||||
@@ -669,6 +671,7 @@
|
||||
#define SDL_ReloadGamepadMappings SDL_ReloadGamepadMappings_REAL
|
||||
#define SDL_RemovePath SDL_RemovePath_REAL
|
||||
#define SDL_RemoveStoragePath SDL_RemoveStoragePath_REAL
|
||||
#define SDL_RemoveSurfaceAlternateImages SDL_RemoveSurfaceAlternateImages_REAL
|
||||
#define SDL_RemoveTimer SDL_RemoveTimer_REAL
|
||||
#define SDL_RenamePath SDL_RenamePath_REAL
|
||||
#define SDL_RenameStoragePath SDL_RenameStoragePath_REAL
|
||||
@@ -845,6 +848,7 @@
|
||||
#define SDL_StopTextInput SDL_StopTextInput_REAL
|
||||
#define SDL_StorageReady SDL_StorageReady_REAL
|
||||
#define SDL_StringToGUID SDL_StringToGUID_REAL
|
||||
#define SDL_SurfaceHasAlternateImages SDL_SurfaceHasAlternateImages_REAL
|
||||
#define SDL_SurfaceHasColorKey SDL_SurfaceHasColorKey_REAL
|
||||
#define SDL_SurfaceHasRLE SDL_SurfaceHasRLE_REAL
|
||||
#define SDL_SyncWindow SDL_SyncWindow_REAL
|
||||
|
||||
@@ -53,6 +53,7 @@ SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromFile,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromIO,(SDL_IOStream *a, SDL_bool b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddSurfaceAlternateImage,(SDL_Surface *a, SDL_Surface *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_TimerID,SDL_AddTimer,(Uint32 a, SDL_TimerCallback b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(SDL_TimerID,SDL_AddTimerNS,(Uint64 a, SDL_NSTimerCallback b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddVulkanRenderSemaphores,(SDL_Renderer *a, Uint32 b, Sint64 c, Sint64 d),(a,b,c,d),return)
|
||||
@@ -483,6 +484,7 @@ SDL_DYNAPI_PROC(int,SDL_GetSurfaceClipRect,(SDL_Surface *a, SDL_Rect *b),(a,b),r
|
||||
SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorKey,(SDL_Surface *a, Uint32 *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorMod,(SDL_Surface *a, Uint8 *b, Uint8 *c, Uint8 *d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(SDL_Colorspace,SDL_GetSurfaceColorspace,(SDL_Surface *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_Surface**,SDL_GetSurfaceImages,(SDL_Surface *a, int *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_Palette*,SDL_GetSurfacePalette,(SDL_Surface *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetSystemRAM,(void),(),return)
|
||||
@@ -680,6 +682,7 @@ SDL_DYNAPI_PROC(int,SDL_ReleaseCameraFrame,(SDL_Camera *a, SDL_Surface *b),(a,b)
|
||||
SDL_DYNAPI_PROC(int,SDL_ReloadGamepadMappings,(void),(),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_RemovePath,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_RemoveStoragePath,(SDL_Storage *a, const char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_RemoveSurfaceAlternateImages,(SDL_Surface *a),(a),)
|
||||
SDL_DYNAPI_PROC(int,SDL_RemoveTimer,(SDL_TimerID a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_RenamePath,(const char *a, const char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_RenameStoragePath,(SDL_Storage *a, const char *b, const char *c),(a,b,c),return)
|
||||
@@ -855,6 +858,7 @@ SDL_DYNAPI_PROC(int,SDL_StopHapticRumble,(SDL_Haptic *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_StopTextInput,(SDL_Window *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_StorageReady,(SDL_Storage *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_GUID,SDL_StringToGUID,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasAlternateImages,(SDL_Surface *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasColorKey,(SDL_Surface *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasRLE,(SDL_Surface *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return)
|
||||
|
||||
@@ -436,6 +436,126 @@ SDL_Palette *SDL_GetSurfacePalette(SDL_Surface *surface)
|
||||
return surface->internal->palette;
|
||||
}
|
||||
|
||||
int SDL_AddSurfaceAlternateImage(SDL_Surface *surface, SDL_Surface *image)
|
||||
{
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
return SDL_InvalidParamError("surface");
|
||||
}
|
||||
|
||||
if (!SDL_SurfaceValid(image)) {
|
||||
return SDL_InvalidParamError("image");
|
||||
}
|
||||
|
||||
SDL_Surface **images = (SDL_Surface **)SDL_realloc(surface->internal->images, (surface->internal->num_images + 1) * sizeof(*images));
|
||||
if (!images) {
|
||||
return -1;
|
||||
}
|
||||
images[surface->internal->num_images] = image;
|
||||
surface->internal->images = images;
|
||||
++surface->internal->num_images;
|
||||
++image->refcount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_bool SDL_SurfaceHasAlternateImages(SDL_Surface *surface)
|
||||
{
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return (surface->internal->num_images > 0);
|
||||
}
|
||||
|
||||
SDL_Surface **SDL_GetSurfaceImages(SDL_Surface *surface, int *count)
|
||||
{
|
||||
if (count) {
|
||||
*count = 0;
|
||||
}
|
||||
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
SDL_InvalidParamError("surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int num_images = 1 + surface->internal->num_images;
|
||||
SDL_Surface **images = (SDL_Surface **)SDL_malloc((num_images + 1) * sizeof(*images));
|
||||
if (!images) {
|
||||
return NULL;
|
||||
}
|
||||
images[0] = surface;
|
||||
if (surface->internal->num_images > 0) {
|
||||
SDL_memcpy(&images[1], surface->internal->images, (surface->internal->num_images * sizeof(images[1])));
|
||||
}
|
||||
images[num_images] = NULL;
|
||||
|
||||
if (count) {
|
||||
*count = num_images;
|
||||
}
|
||||
return images;
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_GetSurfaceImage(SDL_Surface *surface, float display_scale)
|
||||
{
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
SDL_InvalidParamError("surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!SDL_SurfaceHasAlternateImages(surface)) {
|
||||
++surface->refcount;
|
||||
return surface;
|
||||
}
|
||||
|
||||
// This surface has high DPI images, pick the best one available, or scale one to the correct size
|
||||
SDL_Surface **images = SDL_GetSurfaceImages(surface, NULL);
|
||||
if (!images) {
|
||||
// Failure, fall back to the existing surface
|
||||
++surface->refcount;
|
||||
return surface;
|
||||
}
|
||||
|
||||
SDL_Surface *closest = NULL;
|
||||
int desired_w = (int)SDL_round(surface->w * display_scale);
|
||||
int desired_h = (int)SDL_round(surface->h * display_scale);
|
||||
int closest_distance = -1;
|
||||
for (int i = 0; images[i]; ++i) {
|
||||
SDL_Surface *candidate = images[i];
|
||||
int delta_w = (candidate->w - desired_w);
|
||||
int delta_h = (candidate->h - desired_h);
|
||||
int distance = (delta_w * delta_w) + (delta_h * delta_h);
|
||||
if (closest_distance < 0 || distance < closest_distance) {
|
||||
closest = candidate;
|
||||
closest_distance = distance;
|
||||
}
|
||||
}
|
||||
SDL_free(images);
|
||||
SDL_assert(closest != NULL); // We should always have at least one surface
|
||||
|
||||
if (closest->w == desired_w && closest->h == desired_h) {
|
||||
++closest->refcount;
|
||||
return closest;
|
||||
}
|
||||
|
||||
// We need to scale an image to the correct size
|
||||
return SDL_ScaleSurface(closest, desired_w, desired_h, SDL_SCALEMODE_LINEAR);
|
||||
}
|
||||
|
||||
void SDL_RemoveSurfaceAlternateImages(SDL_Surface *surface)
|
||||
{
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->internal->num_images > 0) {
|
||||
for (int i = 0; i < surface->internal->num_images; ++i) {
|
||||
SDL_DestroySurface(surface->internal->images[i]);
|
||||
}
|
||||
SDL_free(surface->internal->images);
|
||||
surface->internal->images = NULL;
|
||||
surface->internal->num_images = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SetSurfaceRLE(SDL_Surface *surface, SDL_bool enabled)
|
||||
{
|
||||
int flags;
|
||||
@@ -1945,6 +2065,13 @@ end:
|
||||
SDL_SetSurfaceRLE(convert, SDL_TRUE);
|
||||
}
|
||||
|
||||
/* Copy alternate images */
|
||||
for (int i = 0; i < surface->internal->num_images; ++i) {
|
||||
if (SDL_AddSurfaceAlternateImage(convert, surface->internal->images[i]) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're ready to go! */
|
||||
return convert;
|
||||
|
||||
@@ -2788,6 +2915,8 @@ void SDL_DestroySurface(SDL_Surface *surface)
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_RemoveSurfaceAlternateImages(surface);
|
||||
|
||||
SDL_DestroyProperties(surface->internal->props);
|
||||
|
||||
SDL_InvalidateMap(&surface->internal->map);
|
||||
|
||||
@@ -52,6 +52,10 @@ struct SDL_SurfaceData
|
||||
/** palette for indexed surfaces */
|
||||
SDL_Palette *palette;
|
||||
|
||||
/** Alternate representation of images */
|
||||
int num_images;
|
||||
SDL_Surface **images;
|
||||
|
||||
/** information needed for surfaces requiring locks */
|
||||
int locked;
|
||||
|
||||
@@ -76,6 +80,7 @@ extern float SDL_GetDefaultSDRWhitePoint(SDL_Colorspace colorspace);
|
||||
extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace colorspace);
|
||||
extern float SDL_GetDefaultHDRHeadroom(SDL_Colorspace colorspace);
|
||||
extern float SDL_GetSurfaceHDRHeadroom(SDL_Surface *surface, SDL_Colorspace colorspace);
|
||||
extern SDL_Surface *SDL_GetSurfaceImage(SDL_Surface *surface, float display_scale);
|
||||
extern int SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode);
|
||||
|
||||
#endif /* SDL_surface_c_h_ */
|
||||
|
||||
Reference in New Issue
Block a user