Skip to content

Commit

Permalink
Added tiled 9-grid texture rendering function
Browse files Browse the repository at this point in the history
* New function SDL_RenderTexture9GridTiled, borders and center is tiled instead of stretched
  • Loading branch information
Oen44 committed Jan 24, 2025
1 parent cb3d6dc commit 6d4e115
Show file tree
Hide file tree
Showing 6 changed files with 362 additions and 0 deletions.
36 changes: 36 additions & 0 deletions include/SDL3/SDL_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -2182,6 +2182,42 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTextureTiled(SDL_Renderer *renderer,
*/
extern SDL_DECLSPEC bool SDLCALL 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);

/**
* Perform a scaled copy using the 9-grid algorithm to the current rendering
* target at subpixel precision.
*
* The pixels in the texture are split into a 3x3 grid, using the different
* corner sizes for each corner, and the sides and center making up the
* remaining pixels. The corners are then scaled using `scale` and fit into
* the corners of the destination rectangle. The sides and center are then
* tiled into place to cover the remaining destination rectangle.
*
* \param renderer the renderer which should copy parts of a texture.
* \param texture the source texture.
* \param srcrect the SDL_Rect structure representing the rectangle to be used
* for the 9-grid, or NULL to use the entire texture.
* \param left_width the width, in pixels, of the left corners in `srcrect`.
* \param right_width the width, in pixels, of the right corners in `srcrect`.
* \param top_height the height, in pixels, of the top corners in `srcrect`.
* \param bottom_height the height, in pixels, of the bottom corners in
* `srcrect`.
* \param scale the scale used to transform the corner of `srcrect` into the
* corner of `dstrect`, or 0.0f for an unscaled copy.
* \param dstrect a pointer to the destination rectangle, or NULL for the
* entire rendering target.
* \param tileScale the scale used to transform the borders and center of `srcrect` into the
* borders and middle of `dstrect`, or 1.0f for an unscaled copy.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function should only be called on the main thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_RenderTexture
*/
extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9GridTiled(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, float tileScale);

/**
* Render a list of triangles, optionally using a texture and indices into the
* vertex array Color and alpha modulation is done per vertex
Expand Down
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,7 @@ SDL3_0.0.0 {
SDL_AudioStreamDevicePaused;
SDL_ClickTrayEntry;
SDL_UpdateTrays;
SDL_RenderTexture9GridTiled;
# extra symbols go here (don't modify this line)
local: *;
};
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1258,3 +1258,4 @@
#define SDL_AudioStreamDevicePaused SDL_AudioStreamDevicePaused_REAL
#define SDL_ClickTrayEntry SDL_ClickTrayEntry_REAL
#define SDL_UpdateTrays SDL_UpdateTrays_REAL
#define SDL_RenderTexture9GridTiled SDL_RenderTexture9GridTiled_REAL
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1266,3 +1266,4 @@ SDL_DYNAPI_PROC(SDL_ThreadState,SDL_GetThreadState,(SDL_Thread *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_AudioStreamDevicePaused,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(void,SDL_ClickTrayEntry,(SDL_TrayEntry *a),(a),)
SDL_DYNAPI_PROC(void,SDL_UpdateTrays,(void),(),)
SDL_DYNAPI_PROC(bool,SDL_RenderTexture9GridTiled,(SDL_Renderer *a,SDL_Texture *b,const SDL_FRect *c,float d,float e,float f,float g,float h,const SDL_FRect *i,float j),(a,b,c,d,e,f,g,h,i,j),return)
135 changes: 135 additions & 0 deletions src/render/SDL_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -4483,6 +4483,141 @@ bool SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const
return true;
}

bool SDL_RenderTexture9GridTiled(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, float tileScale)
{
SDL_FRect full_src, full_dst;
SDL_FRect curr_src, curr_dst;
float dst_left_width;
float dst_right_width;
float dst_top_height;
float dst_bottom_height;

CHECK_RENDERER_MAGIC(renderer, false);
CHECK_TEXTURE_MAGIC(texture, false);

if (renderer != texture->renderer) {
return SDL_SetError("Texture was not created with this renderer");
}

if (!srcrect) {
full_src.x = 0;
full_src.y = 0;
full_src.w = (float)texture->w;
full_src.h = (float)texture->h;
srcrect = &full_src;
}

if (!dstrect) {
GetRenderViewportSize(renderer, &full_dst);
dstrect = &full_dst;
}

if (scale <= 0.0f || scale == 1.0f) {
dst_left_width = SDL_ceilf(left_width);
dst_right_width = SDL_ceilf(right_width);
dst_top_height = SDL_ceilf(top_height);
dst_bottom_height = SDL_ceilf(bottom_height);
} else {
dst_left_width = SDL_ceilf(left_width * scale);
dst_right_width = SDL_ceilf(right_width * scale);
dst_top_height = SDL_ceilf(top_height * scale);
dst_bottom_height = SDL_ceilf(bottom_height * scale);
}

// Center
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_RenderTextureTiled(renderer, texture, &curr_src, tileScale, &curr_dst)) {
return false;
}

// Upper-left corner
curr_src.x = srcrect->x;
curr_src.y = srcrect->y;
curr_src.w = left_width;
curr_src.h = top_height;
curr_dst.x = dstrect->x;
curr_dst.y = dstrect->y;
curr_dst.w = dst_left_width;
curr_dst.h = dst_top_height;
if (!SDL_RenderTexture(renderer, texture, &curr_src, &curr_dst)) {
return false;
}

// Upper-right corner
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)) {
return false;
}

// Lower-right corner
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)) {
return false;
}

// 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)) {
return false;
}

// Left
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_RenderTextureTiled(renderer, texture, &curr_src, tileScale, &curr_dst)) {
return false;
}

// Right
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_RenderTextureTiled(renderer, texture, &curr_src, tileScale, &curr_dst)) {
return false;
}

// Top
curr_src.x = srcrect->x + left_width;
curr_src.y = srcrect->y;
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 - dst_left_width - dst_right_width;
curr_dst.h = dst_top_height;
if (!SDL_RenderTextureTiled(renderer, texture, &curr_src, tileScale, &curr_dst)) {
return false;
}

// Bottom
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_RenderTextureTiled(renderer, texture, &curr_src, tileScale, &curr_dst)) {
return false;
}

return true;
}

bool SDL_RenderGeometry(SDL_Renderer *renderer,
SDL_Texture *texture,
const SDL_Vertex *vertices, int num_vertices,
Expand Down
Loading

0 comments on commit 6d4e115

Please sign in to comment.