Extend the 9-grid functions to handle a non-uniform grid layout (thanks @zaun!)

Fixes https://github.com/libsdl-org/SDL/issues/10389
This commit is contained in:
Sam Lantinga
2024-07-31 22:09:42 -07:00
parent a1c6f99877
commit a5f18048b2
7 changed files with 358 additions and 151 deletions

View File

@@ -68,7 +68,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_AudioDevicePaused,(SDL_AudioDeviceID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_BindAudioStream,(SDL_AudioDeviceID a, SDL_AudioStream *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_BindAudioStreams,(SDL_AudioDeviceID a, SDL_AudioStream **b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_BlitSurface,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_BlitSurface9Grid,(SDL_Surface *a, const SDL_Rect *b, int c, float d, SDL_ScaleMode e, SDL_Surface *f, const SDL_Rect *g),(a,b,c,d,e,f,g),return)
SDL_DYNAPI_PROC(int,SDL_BlitSurface9Grid,(SDL_Surface *a, const SDL_Rect *b, int c, int d, int e, int f, float g, SDL_ScaleMode h, SDL_Surface *i, const SDL_Rect *j),(a,b,c,d,e,f,g,h,i,j),return)
SDL_DYNAPI_PROC(int,SDL_BlitSurfaceScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_BlitSurfaceTiled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_BlitSurfaceTiledWithScale,(SDL_Surface *a, const SDL_Rect *b, float c, SDL_ScaleMode d, SDL_Surface *e, const SDL_Rect *f),(a,b,c,d,e,f),return)
@@ -700,7 +700,7 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_RenderReadPixels,(SDL_Renderer *a, const SDL_Re
SDL_DYNAPI_PROC(int,SDL_RenderRect,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_RenderRects,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderTexture,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, const SDL_FRect *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_RenderTexture9Grid,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, float d, float e, const SDL_FRect *f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(int,SDL_RenderTexture9Grid,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, float d, float e, float f, float g, float h, const SDL_FRect *i),(a,b,c,d,e,f,g,h,i),return)
SDL_DYNAPI_PROC(int,SDL_RenderTextureRotated,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, const SDL_FRect *d, const double e, const SDL_FPoint *f, const SDL_FlipMode g),(a,b,c,d,e,f,g),return)
SDL_DYNAPI_PROC(int,SDL_RenderTextureTiled,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, float d, const SDL_FRect *e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_RenderViewportSet,(SDL_Renderer *a),(a),return)

View File

@@ -4213,11 +4213,14 @@ int SDL_RenderTextureTiled(SDL_Renderer *renderer, SDL_Texture *texture, const S
}
}
int SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float corner_size, float scale, const SDL_FRect *dstrect)
int SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float left_width, float right_width, float top_height, float bottom_height, float scale, const SDL_FRect *dstrect)
{
SDL_FRect full_src, full_dst;
SDL_FRect curr_src, curr_dst;
float dst_corner_size;
float dst_left_width;
float dst_right_width;
float dst_top_height;
float dst_bottom_height;
CHECK_RENDERER_MAGIC(renderer, -1);
CHECK_TEXTURE_MAGIC(texture, -1);
@@ -4240,96 +4243,111 @@ int SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const S
}
if (scale <= 0.0f || scale == 1.0f) {
dst_corner_size = corner_size;
dst_left_width = left_width;
dst_right_width = right_width;
dst_top_height = top_height;
dst_bottom_height = bottom_height;
} else {
dst_corner_size = (corner_size * scale);
dst_left_width = (left_width * scale);
dst_right_width = (right_width * scale);
dst_top_height = (top_height * scale);
dst_bottom_height = (bottom_height * scale);
}
// Upper-left corner
curr_src.x = srcrect->x;
curr_src.y = srcrect->y;
curr_src.w = corner_size;
curr_src.h = corner_size;
curr_src.w = left_width;
curr_src.h = top_height;
curr_dst.x = dstrect->x;
curr_dst.y = dstrect->y;
curr_dst.w = dst_corner_size;
curr_dst.h = dst_corner_size;
curr_dst.w = dst_left_width;
curr_dst.h = dst_top_height;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Upper-right corner
curr_src.x = srcrect->x + srcrect->w - corner_size;
curr_dst.x = dstrect->x + dstrect->w - dst_corner_size;
curr_src.x = srcrect->x + srcrect->w - right_width;
curr_src.w = right_width;
curr_dst.x = dstrect->x + dstrect->w - dst_right_width;
curr_dst.w = dst_right_width;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Lower-right corner
curr_src.y = srcrect->y + srcrect->h - corner_size;
curr_dst.y = dstrect->y + dstrect->h - dst_corner_size;
curr_src.y = srcrect->y + srcrect->h - bottom_height;
curr_dst.y = dstrect->y + dstrect->h - dst_bottom_height;
curr_dst.h = dst_bottom_height;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Lower-left corner
curr_src.x = srcrect->x;
curr_src.w = left_width;
curr_dst.x = dstrect->x;
curr_dst.w = dst_left_width;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Left
curr_src.y = srcrect->y + corner_size;
curr_src.h = srcrect->h - 2 * corner_size;
curr_dst.y = dstrect->y + dst_corner_size;
curr_dst.h = dstrect->h - 2 * dst_corner_size;
curr_src.y = srcrect->y + top_height;
curr_src.h = srcrect->h - top_height - bottom_height;
curr_dst.y = dstrect->y + dst_top_height;
curr_dst.h = dstrect->h - dst_top_height - dst_bottom_height;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Right
curr_src.x = srcrect->x + srcrect->w - corner_size;
curr_dst.x = dstrect->x + dstrect->w - dst_corner_size;
curr_src.x = srcrect->x + srcrect->w - right_width;
curr_src.w = right_width;
curr_dst.x = dstrect->x + dstrect->w - dst_right_width;
curr_dst.w = dst_right_width;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Top
curr_src.x = srcrect->x + corner_size;
curr_src.x = srcrect->x + left_width;
curr_src.y = srcrect->y;
curr_src.w = srcrect->w - 2 * corner_size;
curr_src.h = corner_size;
curr_dst.x = dstrect->x + dst_corner_size;
curr_src.w = srcrect->w - left_width - right_width;
curr_src.h = top_height;
curr_dst.x = dstrect->x + dst_left_width;
curr_dst.y = dstrect->y;
curr_dst.w = dstrect->w - 2 * dst_corner_size;
curr_dst.h = dst_corner_size;
curr_dst.w = dstrect->w - dst_left_width - dst_right_width;
curr_dst.h = dst_top_height;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Bottom
curr_src.y = srcrect->y + srcrect->h - corner_size;
curr_dst.y = dstrect->y + dstrect->h - dst_corner_size;
curr_src.y = srcrect->y + srcrect->h - bottom_height;
curr_dst.y = dstrect->y + dstrect->h - dst_bottom_height;
curr_dst.h = dst_bottom_height;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
// Center
curr_src.x = srcrect->x + corner_size;
curr_src.y = srcrect->y + corner_size;
curr_src.w = srcrect->w - 2 * corner_size;
curr_src.h = srcrect->h - 2 * corner_size;
curr_dst.x = dstrect->x + dst_corner_size;
curr_dst.y = dstrect->y + dst_corner_size;
curr_dst.w = dstrect->w - 2 * dst_corner_size;
curr_dst.h = dstrect->h - 2 * dst_corner_size;
curr_src.x = srcrect->x + left_width;
curr_src.y = srcrect->y + top_height;
curr_src.w = srcrect->w - left_width - right_width;
curr_src.h = srcrect->h - top_height - bottom_height;
curr_dst.x = dstrect->x + dst_left_width;
curr_dst.y = dstrect->y + dst_top_height;
curr_dst.w = dstrect->w - dst_left_width - dst_right_width;
curr_dst.h = dstrect->h - dst_top_height - dst_bottom_height;
if (SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst) < 0) {
return -1;
}
return 0;
}
int SDL_RenderGeometry(SDL_Renderer *renderer,
SDL_Texture *texture,
const SDL_Vertex *vertices, int num_vertices,

View File

@@ -1422,11 +1422,14 @@ int SDL_BlitSurfaceTiledWithScale(SDL_Surface *src, const SDL_Rect *srcrect, flo
return 0;
}
int SDL_BlitSurface9Grid(SDL_Surface *src, const SDL_Rect *srcrect, int corner_size, float scale, SDL_ScaleMode scaleMode, SDL_Surface *dst, const SDL_Rect *dstrect)
int SDL_BlitSurface9Grid(SDL_Surface *src, const SDL_Rect *srcrect, int left_width, int right_width, int top_height, int bottom_height, float scale, SDL_ScaleMode scaleMode, SDL_Surface *dst, const SDL_Rect *dstrect)
{
SDL_Rect full_src, full_dst;
SDL_Rect curr_src, curr_dst;
int dst_corner_size;
int dst_left_width;
int dst_right_width;
int dst_top_height;
int dst_bottom_height;
/* Make sure the surfaces aren't locked */
if (!SDL_SurfaceValid(src)) {
@@ -1452,90 +1455,104 @@ int SDL_BlitSurface9Grid(SDL_Surface *src, const SDL_Rect *srcrect, int corner_s
}
if (scale <= 0.0f || scale == 1.0f) {
dst_corner_size = corner_size;
dst_left_width = left_width;
dst_right_width = right_width;
dst_top_height = top_height;
dst_bottom_height = bottom_height;
} else {
dst_corner_size = (int)SDL_roundf(corner_size * scale);
dst_left_width = (int)SDL_roundf(left_width * scale);
dst_right_width = (int)SDL_roundf(right_width * scale);
dst_top_height = (int)SDL_roundf(top_height * scale);
dst_bottom_height = (int)SDL_roundf(bottom_height * scale);
}
// Upper-left corner
curr_src.x = srcrect->x;
curr_src.y = srcrect->y;
curr_src.w = corner_size;
curr_src.h = corner_size;
curr_src.w = left_width;
curr_src.h = top_height;
curr_dst.x = dstrect->x;
curr_dst.y = dstrect->y;
curr_dst.w = dst_corner_size;
curr_dst.h = dst_corner_size;
curr_dst.w = dst_left_width;
curr_dst.h = dst_top_height;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Upper-right corner
curr_src.x = srcrect->x + srcrect->w - corner_size;
curr_dst.x = dstrect->x + dstrect->w - dst_corner_size;
curr_src.x = srcrect->x + srcrect->w - right_width;
curr_src.w = right_width;
curr_dst.x = dstrect->x + dstrect->w - dst_right_width;
curr_dst.w = dst_right_width;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Lower-right corner
curr_src.y = srcrect->y + srcrect->h - corner_size;
curr_dst.y = dstrect->y + dstrect->h - dst_corner_size;
curr_src.y = srcrect->y + srcrect->h - bottom_height;
curr_dst.y = dstrect->y + dstrect->h - dst_bottom_height;
curr_dst.h = dst_bottom_height;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Lower-left corner
curr_src.x = srcrect->x;
curr_src.w = left_width;
curr_dst.x = dstrect->x;
curr_dst.w = dst_left_width;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Left
curr_src.y = srcrect->y + corner_size;
curr_src.h = srcrect->h - 2 * corner_size;
curr_dst.y = dstrect->y + dst_corner_size;
curr_dst.h = dstrect->h - 2 * dst_corner_size;
curr_src.y = srcrect->y + top_height;
curr_src.h = srcrect->h - top_height - bottom_height;
curr_dst.y = dstrect->y + dst_top_height;
curr_dst.h = dstrect->h - dst_top_height - dst_bottom_height;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Right
curr_src.x = srcrect->x + srcrect->w - corner_size;
curr_dst.x = dstrect->x + dstrect->w - dst_corner_size;
curr_src.x = srcrect->x + srcrect->w - right_width;
curr_src.w = right_width;
curr_dst.x = dstrect->x + dstrect->w - dst_right_width;
curr_dst.w = dst_right_width;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Top
curr_src.x = srcrect->x + corner_size;
curr_src.x = srcrect->x + left_width;
curr_src.y = srcrect->y;
curr_src.w = srcrect->w - 2 * corner_size;
curr_src.h = corner_size;
curr_dst.x = dstrect->x + dst_corner_size;
curr_src.w = srcrect->w - left_width - right_width;
curr_src.h = top_height;
curr_dst.x = dstrect->x + dst_left_width;
curr_dst.y = dstrect->y;
curr_dst.w = dstrect->w - 2 * dst_corner_size;
curr_dst.h = dst_corner_size;
curr_dst.w = dstrect->w - dst_left_width - dst_right_width;
curr_dst.h = dst_top_height;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Bottom
curr_src.y = srcrect->y + srcrect->h - corner_size;
curr_dst.y = dstrect->y + dstrect->h - dst_corner_size;
curr_src.y = srcrect->y + srcrect->h - bottom_height;
curr_dst.y = dstrect->y + dstrect->h - dst_bottom_height;
curr_dst.h = dst_bottom_height;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}
// Center
curr_src.x = srcrect->x + corner_size;
curr_src.y = srcrect->y + corner_size;
curr_src.w = srcrect->w - 2 * corner_size;
curr_src.h = srcrect->h - 2 * corner_size;
curr_dst.x = dstrect->x + dst_corner_size;
curr_dst.y = dstrect->y + dst_corner_size;
curr_dst.w = dstrect->w - 2 * dst_corner_size;
curr_dst.h = dstrect->h - 2 * dst_corner_size;
curr_src.x = srcrect->x + left_width;
curr_src.y = srcrect->y + top_height;
curr_src.w = srcrect->w - left_width - right_width;
curr_src.h = srcrect->h - top_height - bottom_height;
curr_dst.x = dstrect->x + dst_left_width;
curr_dst.y = dstrect->y + dst_top_height;
curr_dst.w = dstrect->w - dst_left_width - dst_right_width;
curr_dst.h = dstrect->h - dst_top_height - dst_bottom_height;
if (SDL_BlitSurfaceScaled(src, &curr_src, dst, &curr_dst, scaleMode) < 0) {
return -1;
}