Browse Source

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

Fixes https://github.com/libsdl-org/SDL/issues/10389
Sam Lantinga 8 tháng trước cách đây
mục cha
commit
a5f18048b2

+ 10 - 7
include/SDL3/SDL_render.h

@@ -1919,17 +1919,20 @@ extern SDL_DECLSPEC int SDLCALL SDL_RenderTextureTiled(SDL_Renderer *renderer, S
  * 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 corner size
- * 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 stretched into place
- * to cover the remaining destination rectangle.
+ * 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
+ * stretched 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 corner_size the size, in pixels, of the corner in `srcrect`.
+ * \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
@@ -1941,7 +1944,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_RenderTextureTiled(SDL_Renderer *renderer, S
  *
  * \sa SDL_RenderTexture
  */
-extern SDL_DECLSPEC int SDLCALL SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float corner_size, float scale, const SDL_FRect *dstrect);
+extern SDL_DECLSPEC int 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);
 
 /**
  * Render a list of triangles, optionally using a texture and indices into the

+ 7 - 4
include/SDL3/SDL_surface.h

@@ -1105,8 +1105,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_BlitSurfaceTiledWithScale(SDL_Surface *src,
  * Perform a scaled blit using the 9-grid algorithm to a destination surface,
  * which may be of a different format.
  *
- * The pixels in the source surface are split into a 3x3 grid, using the
- * corner size for each corner, and the sides and center making up the
+ * The pixels in the source surface 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
  * stretched into place to cover the remaining destination rectangle.
@@ -1114,7 +1114,10 @@ extern SDL_DECLSPEC int SDLCALL SDL_BlitSurfaceTiledWithScale(SDL_Surface *src,
  * \param src the SDL_Surface structure to be copied from.
  * \param srcrect the SDL_Rect structure representing the rectangle to be used
  *                for the 9-grid, or NULL to use the entire surface.
- * \param corner_size the size, in pixels, of the corner in `srcrect`.
+ * \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 blit.
  * \param scaleMode scale algorithm to be used.
@@ -1132,7 +1135,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_BlitSurfaceTiledWithScale(SDL_Surface *src,
  *
  * \sa SDL_BlitSurface
  */
-extern SDL_DECLSPEC int SDLCALL SDL_BlitSurface9Grid(SDL_Surface *src, const SDL_Rect *srcrect, int corner_size, float scale, SDL_ScaleMode scaleMode, SDL_Surface *dst, const SDL_Rect *dstrect);
+extern SDL_DECLSPEC int SDLCALL 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);
 
 /**
  * Map an RGB triple to an opaque pixel value for a surface.

+ 2 - 2
src/dynapi/SDL_dynapi_procs.h

@@ -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)

+ 52 - 34
src/render/SDL_render.c

@@ -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,

+ 51 - 34
src/video/SDL_surface.c

@@ -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;
     }

+ 133 - 35
test/testautomation_render.c

@@ -367,71 +367,71 @@ static int render_testBlitTiled(void *arg)
 
 static const Uint8 COLOR_SEPARATION = 85;
 
-static void Fill9GridReferenceSurface(SDL_Surface *surface, int corner_size)
+static void Fill9GridReferenceSurface(SDL_Surface *surface, int left_width, int right_width, int top_height, int bottom_height)
 {
     SDL_Rect rect;
 
     // Upper left
     rect.x = 0;
     rect.y = 0;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.w = left_width;
+    rect.h = top_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
 
     // Top
-    rect.x = corner_size;
+    rect.x = left_width;
     rect.y = 0;
-    rect.w = surface->w - 2 * corner_size;
-    rect.h = corner_size;
+    rect.w = surface->w - left_width - right_width;
+    rect.h = top_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
 
     // Upper right
-    rect.x = surface->w - corner_size;
+    rect.x = surface->w - right_width;
     rect.y = 0;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.w = right_width;
+    rect.h = top_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
 
     // Left
     rect.x = 0;
-    rect.y = corner_size;
-    rect.w = corner_size;
-    rect.h = surface->h - 2 * corner_size;
+    rect.y = top_height;
+    rect.w = left_width;
+    rect.h = surface->h - top_height - bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
 
     // Center
-    rect.x = corner_size;
-    rect.y = corner_size;
-    rect.w = surface->w - 2 * corner_size;
-    rect.h = surface->h - 2 * corner_size;
+    rect.x = left_width;
+    rect.y = top_height;
+    rect.w = surface->w - right_width - left_width;
+    rect.h = surface->h - top_height - bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
 
     // Right
-    rect.x = surface->w - corner_size;
-    rect.y = corner_size;
-    rect.w = corner_size;
-    rect.h = surface->h - 2 * corner_size;
+    rect.x = surface->w - right_width;
+    rect.y = top_height;
+    rect.w = right_width;
+    rect.h = surface->h - top_height - bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
 
     // Lower left
     rect.x = 0;
-    rect.y = surface->h - corner_size;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.y = surface->h - bottom_height;
+    rect.w = left_width;
+    rect.h = bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
 
     // Bottom
-    rect.x = corner_size;
-    rect.y = surface->h - corner_size;
-    rect.w = surface->w - 2 * corner_size;
-    rect.h = corner_size;
+    rect.x = left_width;
+    rect.y = surface->h - bottom_height;
+    rect.w = surface->w - left_width - right_width;
+    rect.h = bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
 
     // Lower right
-    rect.x = surface->w - corner_size;
-    rect.y = surface->h - corner_size;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.x = surface->w - right_width;
+    rect.y = surface->h - bottom_height;
+    rect.w = right_width;
+    rect.h = bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
 }
 
@@ -462,11 +462,12 @@ static int render_testBlit9Grid(void *arg)
 
     /* 9-grid blit - 1.0 scale */
     {
+        SDLTest_Log("9-grid blit - 1.0 scale");
         /* Create reference surface */
         SDL_DestroySurface(referenceSurface);
         referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
         SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
-        Fill9GridReferenceSurface(referenceSurface, 1);
+        Fill9GridReferenceSurface(referenceSurface, 1, 1, 1, 1);
 
         /* Clear surface. */
         clearScreen();
@@ -476,7 +477,7 @@ static int render_testBlit9Grid(void *arg)
         rect.y = 0.0f;
         rect.w = (float)TESTRENDER_SCREEN_W;
         rect.h = (float)TESTRENDER_SCREEN_H;
-        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 1.0f, &rect);
+        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, &rect);
         SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
 
         /* See if it's the same */
@@ -488,11 +489,12 @@ static int render_testBlit9Grid(void *arg)
 
     /* 9-grid blit - 2.0 scale */
     {
+        SDLTest_Log("9-grid blit - 2.0 scale");
         /* Create reference surface */
         SDL_DestroySurface(referenceSurface);
         referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
         SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
-        Fill9GridReferenceSurface(referenceSurface, 2);
+        Fill9GridReferenceSurface(referenceSurface, 2, 2, 2, 2);
 
         /* Clear surface. */
         clearScreen();
@@ -502,7 +504,103 @@ static int render_testBlit9Grid(void *arg)
         rect.y = 0.0f;
         rect.w = (float)TESTRENDER_SCREEN_W;
         rect.h = (float)TESTRENDER_SCREEN_H;
-        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 2.0f, &rect);
+        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, &rect);
+        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
+
+        /* See if it's the same */
+        compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
+
+        /* Make current */
+        SDL_RenderPresent(renderer);
+    }
+
+    /* Clean up. */
+    SDL_DestroySurface(source);
+    SDL_DestroyTexture(texture);
+
+    /* Create complex source surface */
+    source = SDL_CreateSurface(5, 5, SDL_PIXELFORMAT_RGBA32);
+    SDLTest_AssertCheck(source != NULL, "Verify source surface is not NULL");
+    SDL_WriteSurfacePixel(source, 0, 0, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 0, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 0, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 0, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 0, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 1, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 1, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 1, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 1, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 1, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 2, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 2, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 2, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 2, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 2, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 3, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 3, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 3, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 3, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 3, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 4, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 4, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 4, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 4, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 4, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+
+    texture = SDL_CreateTextureFromSurface(renderer, source);
+    SDLTest_AssertCheck(texture != NULL, "Verify source texture is not NULL");
+    ret = SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
+    SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_SetTextureScaleMode, expected: 0, got: %i", ret);
+
+    /* complex 9-grid blit - 1.0 scale */
+    {
+        SDLTest_Log("complex 9-grid blit - 1.0 scale");
+        /* Create reference surface */
+        SDL_DestroySurface(referenceSurface);
+        referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
+        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
+        Fill9GridReferenceSurface(referenceSurface, 1, 2, 1, 2);
+
+        /* Clear surface. */
+        clearScreen();
+
+        /* Tiled blit. */
+        rect.x = 0.0f;
+        rect.y = 0.0f;
+        rect.w = (float)TESTRENDER_SCREEN_W;
+        rect.h = (float)TESTRENDER_SCREEN_H;
+        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 2.0f, 1.0f, 2.0f, 1.0f, &rect);
+        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
+
+        /* See if it's the same */
+        compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
+
+        /* Make current */
+        SDL_RenderPresent(renderer);
+    }
+
+    /* complex 9-grid blit - 2.0 scale */
+    {
+        SDLTest_Log("complex 9-grid blit - 2.0 scale");
+        /* Create reference surface */
+        SDL_DestroySurface(referenceSurface);
+        referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
+        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
+        Fill9GridReferenceSurface(referenceSurface, 2, 4, 2, 4);
+
+        /* Clear surface. */
+        clearScreen();
+
+        /* Tiled blit. */
+        rect.x = 0.0f;
+        rect.y = 0.0f;
+        rect.w = (float)TESTRENDER_SCREEN_W;
+        rect.h = (float)TESTRENDER_SCREEN_H;
+        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 2.0f, 1.0f, 2.0f, 2.0f, &rect);
         SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
 
         /* See if it's the same */

+ 103 - 35
test/testautomation_surface.c

@@ -417,71 +417,71 @@ static int surface_testBlitTiled(void *arg)
 
 static const Uint8 COLOR_SEPARATION = 85;
 
-static void Fill9GridReferenceSurface(SDL_Surface *surface, int corner_size)
+static void Fill9GridReferenceSurface(SDL_Surface *surface, int left_width, int right_width, int top_height, int bottom_height)
 {
     SDL_Rect rect;
 
     // Upper left
     rect.x = 0;
     rect.y = 0;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.w = left_width;
+    rect.h = top_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
 
     // Top
-    rect.x = corner_size;
+    rect.x = left_width;
     rect.y = 0;
-    rect.w = surface->w - 2 * corner_size;
-    rect.h = corner_size;
+    rect.w = surface->w - left_width - right_width;
+    rect.h = top_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
 
     // Upper right
-    rect.x = surface->w - corner_size;
+    rect.x = surface->w - right_width;
     rect.y = 0;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.w = right_width;
+    rect.h = top_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
 
     // Left
     rect.x = 0;
-    rect.y = corner_size;
-    rect.w = corner_size;
-    rect.h = surface->h - 2 * corner_size;
+    rect.y = top_height;
+    rect.w = left_width;
+    rect.h = surface->h - top_height - bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
 
     // Center
-    rect.x = corner_size;
-    rect.y = corner_size;
-    rect.w = surface->w - 2 * corner_size;
-    rect.h = surface->h - 2 * corner_size;
+    rect.x = left_width;
+    rect.y = top_height;
+    rect.w = surface->w - right_width - left_width;
+    rect.h = surface->h - top_height - bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
 
     // Right
-    rect.x = surface->w - corner_size;
-    rect.y = corner_size;
-    rect.w = corner_size;
-    rect.h = surface->h - 2 * corner_size;
+    rect.x = surface->w - right_width;
+    rect.y = top_height;
+    rect.w = right_width;
+    rect.h = surface->h - top_height - bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
 
     // Lower left
     rect.x = 0;
-    rect.y = surface->h - corner_size;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.y = surface->h - bottom_height;
+    rect.w = left_width;
+    rect.h = bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
 
     // Bottom
-    rect.x = corner_size;
-    rect.y = surface->h - corner_size;
-    rect.w = surface->w - 2 * corner_size;
-    rect.h = corner_size;
+    rect.x = left_width;
+    rect.y = surface->h - bottom_height;
+    rect.w = surface->w - left_width - right_width;
+    rect.h = bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
 
     // Lower right
-    rect.x = surface->w - corner_size;
-    rect.y = surface->h - corner_size;
-    rect.w = corner_size;
-    rect.h = corner_size;
+    rect.x = surface->w - right_width;
+    rect.y = surface->h - bottom_height;
+    rect.w = right_width;
+    rect.h = bottom_height;
     SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
 }
 
@@ -509,9 +509,9 @@ static int surface_testBlit9Grid(void *arg)
         SDL_DestroySurface(referenceSurface);
         referenceSurface = SDL_CreateSurface(testSurface->w, testSurface->h, testSurface->format);
         SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
-        Fill9GridReferenceSurface(referenceSurface, 1);
+        Fill9GridReferenceSurface(referenceSurface, 1, 1, 1, 1);
 
-        ret = SDL_BlitSurface9Grid(source, NULL, 1, 0.0f, SDL_SCALEMODE_NEAREST, testSurface, NULL);
+        ret = SDL_BlitSurface9Grid(source, NULL, 1, 1, 1, 1, 0.0f, SDL_SCALEMODE_NEAREST, testSurface, NULL);
         SDLTest_AssertCheck(ret == 0, "Validate result from SDL_BlitSurface9Grid, expected: 0, got: %i", ret);
 
         ret = SDLTest_CompareSurfaces(testSurface, referenceSurface, 0);
@@ -524,9 +524,77 @@ static int surface_testBlit9Grid(void *arg)
         SDL_DestroySurface(referenceSurface);
         referenceSurface = SDL_CreateSurface(testSurface->w, testSurface->h, testSurface->format);
         SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
-        Fill9GridReferenceSurface(referenceSurface, 2);
+        Fill9GridReferenceSurface(referenceSurface, 2, 2, 2, 2);
 
-        ret = SDL_BlitSurface9Grid(source, NULL, 1, 2.0f, SDL_SCALEMODE_NEAREST, testSurface, NULL);
+        ret = SDL_BlitSurface9Grid(source, NULL, 1, 1, 1, 1, 2.0f, SDL_SCALEMODE_NEAREST, testSurface, NULL);
+        SDLTest_AssertCheck(ret == 0, "Validate result from SDL_BlitSurface9Grid, expected: 0, got: %i", ret);
+
+        ret = SDLTest_CompareSurfaces(testSurface, referenceSurface, 0);
+        SDLTest_AssertCheck(ret == 0, "Validate result from SDLTest_CompareSurfaces, expected: 0, got: %i", ret);
+    }
+
+    /* Clean up. */
+    SDL_DestroySurface(source);
+
+    /* Create complex source surface */
+    source = SDL_CreateSurface(5, 5, SDL_PIXELFORMAT_RGBA32);
+    SDLTest_AssertCheck(source != NULL, "Verify source surface is not NULL");
+    SDL_WriteSurfacePixel(source, 0, 0, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 0, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 0, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 0, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 0, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 1, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 1, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 1, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 1, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 1, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 2, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 2, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 2, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 2, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 2, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 3, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 3, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 3, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 3, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 3, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+
+    SDL_WriteSurfacePixel(source, 0, 4, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 1, 4, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 2, 4, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 3, 4, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+    SDL_WriteSurfacePixel(source, 4, 4, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
+
+    /* complex 9-grid blit - 1.0 scale */
+    {
+        SDLTest_Log("complex 9-grid blit - 1.0 scale");
+        /* Create reference surface */
+        SDL_DestroySurface(referenceSurface);
+        referenceSurface = SDL_CreateSurface(testSurface->w, testSurface->h, testSurface->format);
+        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
+        Fill9GridReferenceSurface(referenceSurface, 1, 2, 1, 2);
+
+        ret = SDL_BlitSurface9Grid(source, NULL, 1, 2, 1, 2, 0.0f, SDL_SCALEMODE_NEAREST, testSurface, NULL);
+        SDLTest_AssertCheck(ret == 0, "Validate result from SDL_BlitSurface9Grid, expected: 0, got: %i", ret);
+
+        ret = SDLTest_CompareSurfaces(testSurface, referenceSurface, 0);
+        SDLTest_AssertCheck(ret == 0, "Validate result from SDLTest_CompareSurfaces, expected: 0, got: %i", ret);
+    }
+
+    /* complex 9-grid blit - 2.0 scale */
+    {
+        SDLTest_Log("complex 9-grid blit - 2.0 scale");
+        /* Create reference surface */
+        SDL_DestroySurface(referenceSurface);
+        referenceSurface = SDL_CreateSurface(testSurface->w, testSurface->h, testSurface->format);
+        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
+        Fill9GridReferenceSurface(referenceSurface, 2, 4, 2, 4);
+
+        ret = SDL_BlitSurface9Grid(source, NULL, 1, 2, 1, 2, 2.0f, SDL_SCALEMODE_NEAREST, testSurface, NULL);
         SDLTest_AssertCheck(ret == 0, "Validate result from SDL_BlitSurface9Grid, expected: 0, got: %i", ret);
 
         ret = SDLTest_CompareSurfaces(testSurface, referenceSurface, 0);