Skip to content

Instantly share code, notes, and snippets.

@NickBeeuwsaert
Last active August 29, 2015 14:07
Show Gist options
  • Select an option

  • Save NickBeeuwsaert/38cd67c645e40215d51d to your computer and use it in GitHub Desktop.

Select an option

Save NickBeeuwsaert/38cd67c645e40215d51d to your computer and use it in GitHub Desktop.
Drawing scalable images in SDL2
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdbool.h>
#define MAX(a, b) ((a)>(b)?(a):(b))
/**
* Renders a image with out distorting it
*
* @param renderer The renderer to render to
* @param patch The texture to render
* @param src the offsets from the edges of the texture to cut the image
* @param dst The destination where the patch will be drawn
*/
void RenderPatch(SDL_Renderer * renderer, SDL_Texture *patch, SDL_Rect *src, SDL_Rect *dst) {
//Create a copy of the dst rect so we can modify it
SDL_Rect frame = *dst;
//Make sure that the dst isn't too small
// Sort of like how CSS box-sizing: border-box; works
// if we have a width of 50px, but the padding is set to 30px, then we will have a 60px wide box
frame.w = MAX(frame.w, src->x+src->w);
frame.h = MAX(frame.h, src->y+src->h);
int w, h;
SDL_QueryTexture(patch, NULL, NULL, &w, &h);
SDL_Point srcPoints[] = {
{0, 0},
{src->x, src->y},
{w - src->w, h - src->h},
{w, h}
};
SDL_Point dstPoints[] = {
{frame.x, frame.y},
{frame.x + src->x, frame.y + src->y},
{frame.x + frame.w - src->w, frame.y + frame.h - src->h},
{frame.x + frame.w, frame.y + frame.h}
};
//Loop trough and draw each rect
for (int y = 0; y < 3; y++ ) {
for (int x = 0; x < 3; x++) {
SDL_Rect src_ = {
srcPoints[x].x,
srcPoints[y].y,
srcPoints[x+1].x,
srcPoints[y+1].y
};
src_.w -= src_.x;
src_.h -= src_.y;
SDL_Rect dst_ = {
dstPoints[x].x,
dstPoints[y].y,
dstPoints[x+1].x,
dstPoints[y+1].y
};
dst_.w -= dst_.x;
dst_.h -= dst_.y;
SDL_RenderCopy(renderer, patch, &src_, &dst_);
}
}
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG);
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Event evt;
SDL_Texture *texture;
if (SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_OPENGL, &window, &renderer) != 0) {
fprintf(stderr, "Problem creating window and renderer: %s\n", SDL_GetError());
return -1;
}
if( !(texture = IMG_LoadTexture(renderer, "texture.png"))) {
fprintf(stderr, "Problem loading texture!\n");
return -1;
}
// Use a white background so you can see my pretty drop shadows
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Rect patch_border = {30, 82, 30, 30};
bool running = true;
while(running) {
SDL_RenderClear(renderer);
SDL_Rect frame;
//A. Draw a medium sized window in the top left
frame = (SDL_Rect){0, 0, 266, 300};
RenderPatch(renderer, texture, &patch_border, &frame);
//B. Draw half that in the top center
frame = (SDL_Rect){266+75, 0, 133, 150};
RenderPatch(renderer, texture, &patch_border, &frame);
//C. Draw a 0x0 window to show how small sizes are handled (Badly)
frame = (SDL_Rect){266*2+30, 0, 0, 0};
RenderPatch(renderer, texture, &patch_border, &frame);
//D. Draw a window with the same dimensions as D
frame = (SDL_Rect){266*2+90, 0, 60, 112};
RenderPatch(renderer, texture, &patch_border, &frame);
//Draw a large window along the bottom
frame = (SDL_Rect){0, 300, 800, 300};
RenderPatch(renderer, texture, &patch_border, &frame);
SDL_RenderPresent(renderer);
while(SDL_PollEvent(&evt)) {
switch(evt.type) {
case SDL_QUIT:
running = false;
break;
}
}
}
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
return 0;
}
LIBS=`sdl2-config --libs` `pkg-config SDL2_image --libs`
CFLAGS=`sdl2-config --cflags` `pkg-config SDL2_image --cflags`
all: main.o
gcc -o main main.o $(LIBS) -Wall
main.o: main.c
gcc -o main.o -c main.c $(CFLAGS) -Wall
clean:
rm main.o main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment