From 0ecb3a7c3ac933d753e7e7bfe2ae339232d8dea3 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 8 Jan 2026 16:54:24 -0800
Subject: [PATCH] Orientation can use properties instead of modifying the
surface
---
examples/showimage.c | 53 ++++++++++++++++++++++----
src/IMG.c | 90 ++++++++++++++++++++++++--------------------
2 files changed, 95 insertions(+), 48 deletions(-)
diff --git a/examples/showimage.c b/examples/showimage.c
index 9cf8da26..d620f976 100644
--- a/examples/showimage.c
+++ b/examples/showimage.c
@@ -23,6 +23,9 @@
#include <SDL3/SDL_main.h>
#include <SDL3_image/SDL_image.h>
+#ifndef SDL_PROP_SURFACE_FLIP_NUMBER
+#define SDL_PROP_SURFACE_FLIP_NUMBER "SDL.surface.flip"
+#endif
/* Draw a Gimpish background pattern to show transparency in the image */
static void draw_background(SDL_Renderer *renderer)
@@ -79,7 +82,7 @@ static void set_cursor(const char *cursor_file)
}
}
-static SDL_Texture *load_image(SDL_Renderer *renderer, const char *file, const char *tonemap, float *rotation)
+static SDL_Texture *load_image(SDL_Renderer *renderer, const char *file, const char *tonemap, SDL_FlipMode *flip, float *rotation)
{
SDL_Texture *texture = NULL;
SDL_Surface *surface = IMG_Load(get_file_path(file));
@@ -102,6 +105,7 @@ static SDL_Texture *load_image(SDL_Renderer *renderer, const char *file, const c
surface = temp;
}
+ *flip = SDL_GetNumberProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_FLIP_NUMBER, SDL_FLIP_NONE);
*rotation = SDL_GetFloatProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_ROTATION_FLOAT, 0.0f);
texture = SDL_CreateTextureFromSurface(renderer, surface);
@@ -114,6 +118,7 @@ int main(int argc, char *argv[])
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *texture = NULL;
+ SDL_FlipMode flip = SDL_FLIP_NONE;
float rotation = 0.0f;
Uint32 flags;
int i;
@@ -204,7 +209,7 @@ int main(int argc, char *argv[])
/* Open the image file */
++attempted;
- texture = load_image(renderer, argv[i], tonemap, &rotation);
+ texture = load_image(renderer, argv[i], tonemap, &flip, &rotation);
if (!texture) {
continue;
}
@@ -225,7 +230,11 @@ int main(int argc, char *argv[])
/* Show the window */
SDL_SetWindowTitle(window, argv[i]);
- SDL_SetWindowSize(window, texture->w, texture->h);
+ if (rotation == 90.0f || rotation == 270.0f) {
+ SDL_SetWindowSize(window, texture->h, texture->w);
+ } else {
+ SDL_SetWindowSize(window, texture->w, texture->h);
+ }
SDL_ShowWindow(window);
done = quit;
@@ -272,7 +281,20 @@ int main(int argc, char *argv[])
draw_background(renderer);
/* Display the image */
- SDL_RenderTextureRotated(renderer, texture, NULL, NULL, rotation, NULL, SDL_FLIP_NONE);
+ SDL_FRect dst;
+ if (rotation == 90.0f || rotation == 270.0f) {
+ // Use a pre-rotated destination rectangle
+ dst.x = -(texture->w - texture->h) / 2.0f;
+ dst.y = (texture->w - texture->h) / 2.0f;
+ dst.w = (float)texture->w;
+ dst.h = (float)texture->h;
+ } else {
+ dst.x = 0.0f;
+ dst.y = 0.0f;
+ dst.w = (float)texture->w;
+ dst.h = (float)texture->h;
+ }
+ SDL_RenderTextureRotated(renderer, texture, NULL, &dst, rotation, NULL, flip);
SDL_RenderPresent(renderer);
SDL_Delay(100);
@@ -297,12 +319,16 @@ int main(int argc, char *argv[])
SDL_DestroyTexture(texture);
SDL_Log("Loading %s\n", file);
- texture = load_image(renderer, file, tonemap, &rotation);
+ texture = load_image(renderer, file, tonemap, &flip, &rotation);
if (!texture) {
break;
}
SDL_SetWindowTitle(window, file);
- SDL_SetWindowSize(window, texture->w, texture->h);
+ if (rotation == 90.0f || rotation == 270.0f) {
+ SDL_SetWindowSize(window, texture->h, texture->w);
+ } else {
+ SDL_SetWindowSize(window, texture->w, texture->h);
+ }
}
break;
case SDL_EVENT_KEY_UP:
@@ -328,7 +354,20 @@ int main(int argc, char *argv[])
draw_background(renderer);
/* Display the image */
- SDL_RenderTextureRotated(renderer, texture, NULL, NULL, rotation, NULL, SDL_FLIP_NONE);
+ SDL_FRect dst;
+ if (rotation == 90.0f || rotation == 270.0f) {
+ // Use a pre-rotated destination rectangle
+ dst.x = -(texture->w - texture->h) / 2.0f;
+ dst.y = (texture->w - texture->h) / 2.0f;
+ dst.w = (float)texture->w;
+ dst.h = (float)texture->h;
+ } else {
+ dst.x = 0.0f;
+ dst.y = 0.0f;
+ dst.w = (float)texture->w;
+ dst.h = (float)texture->h;
+ }
+ SDL_RenderTextureRotated(renderer, texture, NULL, &dst, rotation, NULL, flip);
SDL_RenderPresent(renderer);
SDL_Delay(100);
diff --git a/src/IMG.c b/src/IMG.c
index ca913e9b..cdd23eb9 100644
--- a/src/IMG.c
+++ b/src/IMG.c
@@ -27,6 +27,10 @@
#include <emscripten/emscripten.h>
#endif
+#ifndef SDL_PROP_SURFACE_FLIP_NUMBER
+#define SDL_PROP_SURFACE_FLIP_NUMBER "SDL.surface.flip"
+#endif
+
#if defined(SDL_BUILD_MAJOR_VERSION)
SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MAJOR_VERSION,
SDL_IMAGE_MAJOR_VERSION == SDL_BUILD_MAJOR_VERSION);
@@ -549,66 +553,70 @@ Uint64 IMG_TimebaseDuration(Uint64 pts, Uint64 duration, Uint64 src_numerator, U
SDL_Surface *IMG_ApplyOrientation(SDL_Surface *surface, int orientation)
{
- SDL_Surface *tmp;
- switch (orientation)
- {
+ float rotation = 0.0f;
+ SDL_FlipMode flip = SDL_FLIP_NONE;
+ switch (orientation) {
case 1:
// Normal (no rotation required)
break;
case 2:
- // Flipped horizontally
- if (!SDL_FlipSurface(surface, SDL_FLIP_HORIZONTAL)) {
- SDL_DestroySurface(surface);
- return NULL;
- }
+ // Mirror horizontal
+ flip = SDL_FLIP_HORIZONTAL;
break;
case 3:
- // Upside-down (180 degrees rotation)
- tmp = SDL_RotateSurface(surface, 180.0f);
- SDL_DestroySurface(surface);
- surface = tmp;
+ // Rotate 180
+ rotation = 180.0f;
break;
case 4:
- // Flipped vertically
- if (!SDL_FlipSurface(surface, SDL_FLIP_VERTICAL)) {
- SDL_DestroySurface(surface);
- return NULL;
- }
+ // Mirror vertical
+ flip = SDL_FLIP_VERTICAL;
break;
case 5:
- // Flip horizontally and rotate 90 degrees counterclockwise
- if (!SDL_FlipSurface(surface, SDL_FLIP_HORIZONTAL)) {
- SDL_DestroySurface(surface);
- return NULL;
- }
- tmp = SDL_RotateSurface(surface, -90.0f);
- SDL_DestroySurface(surface);
- surface = tmp;
+ // Mirror horizontal and rotate 270 CW
+ flip = SDL_FLIP_HORIZONTAL;
+ rotation = 270.0f;
break;
case 6:
- // Rotate 90 degrees clockwise
- tmp = SDL_RotateSurface(surface, 90.0f);
- SDL_DestroySurface(surface);
- surface = tmp;
+ // Rotate 90 CW
+ rotation = 90.0f;
break;
case 7:
- // Flip horizontally and rotate 90 degrees clockwise
- if (!SDL_FlipSurface(surface, SDL_FLIP_HORIZONTAL)) {
- SDL_DestroySurface(surface);
- return NULL;
- }
- tmp = SDL_RotateSurface(surface, 90.0f);
- SDL_DestroySurface(surface);
- surface = tmp;
+ // Mirror horizontal and rotate 90 CW
+ flip = SDL_FLIP_HORIZONTAL;
+ rotation = 90.0f;
break;
case 8:
- // Rotate 90 degrees counterclockwise
- tmp = SDL_RotateSurface(surface, -90.0f);
- SDL_DestroySurface(surface);
- surface = tmp;
+ // Rotate 270 CW
+ rotation = 270.0f;
break;
default:
break;
}
+
+#ifdef ORIENTATION_USES_PROPERTIES
+ if (flip != SDL_FLIP_NONE) {
+ SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
+ SDL_SetNumberProperty(props, SDL_PROP_SURFACE_FLIP_NUMBER, flip);
+ }
+ if (rotation != 0.0f) {
+ SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
+ SDL_SetFloatProperty(props, SDL_PROP_SURFACE_ROTATION_FLOAT, rotation);
+ }
+#else
+ if (flip != SDL_FLIP_NONE) {
+ if (!SDL_FlipSurface(surface, flip)) {
+ SDL_DestroySurface(surface);
+ return NULL;
+ }
+ }
+ if (rotation != 0.0f) {
+ SDL_Surface *tmp = SDL_RotateSurface(surface, rotation);
+ SDL_DestroySurface(surface);
+ if (!tmp) {
+ return NULL;
+ }
+ surface = tmp;
+ }
+#endif
return surface;
}