diff options
author | Your Name <you@example.com> | 2020-10-12 00:02:22 +0000 |
---|---|---|
committer | Your Name <you@example.com> | 2020-10-12 00:02:22 +0000 |
commit | 286f93b894864a8a2dbe9ca34a4c18fd456790b7 (patch) | |
tree | 0a2db90634366a43670a729cecec5844621de868 /main.c | |
download | OSXIV-286f93b894864a8a2dbe9ca34a4c18fd456790b7.tar.gz OSXIV-286f93b894864a8a2dbe9ca34a4c18fd456790b7.tar.bz2 OSXIV-286f93b894864a8a2dbe9ca34a4c18fd456790b7.zip |
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/main.c b/main.c new file mode 100644 index 0000000..898aace --- /dev/null +++ b/main.c @@ -0,0 +1,199 @@ +/* + OSXIV - Overly Simple X Image Viewer +*/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <SDL2/SDL.h> +#include <SDL2/SDL_image.h> + +#define DEBUG 0 + +int main(int argc, char** argv); +int render(double zoom, double move_x, double move_y); +int handle_events(); +void cleanup(); + +#define DBG(fmt, ...) do { if (DEBUG) printf(fmt, __VA_ARGS__); } while (0) + +SDL_Window *window = NULL; +SDL_Renderer *renderer = NULL; +SDL_Texture *texture = NULL; + +int main(int argc, char** argv) +{ + if(argc < 2) + { + fprintf(stderr, "Please provide a filename (or '-' to read from stdin).\n"); + return 1; + } + + if(strcmp(argv[1], "-") && access(argv[1], F_OK ) == -1) + { + fprintf(stderr, "Filename doesnt exist.\n"); + return 1; + } + + SDL_Init(SDL_INIT_VIDEO); + IMG_Init(IMG_INIT_PNG); + + atexit(cleanup); + + char* windowtitle = malloc(sizeof(char) * (9 + strlen(strcmp(argv[1], "-") ? argv[1] : "stdin"))); // +9 bcz "OSXIV - " + sprintf(windowtitle, "OSXIV - %s", strcmp(argv[1], "-") ? argv[1] : "stdin"); + + SDL_DisplayMode dm; + SDL_GetCurrentDisplayMode(0, &dm); + + window = SDL_CreateWindow( + windowtitle, + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + dm.w / 2, //w + dm.h / 2, //h + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE + ); + + free(windowtitle); + + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE); + + SDL_RWops* img; + if(!strcmp(argv[1], "-")) + img = SDL_RWFromFP(stdin, 0); + else + img = SDL_RWFromFile(argv[1], "rb"); + texture = IMG_LoadTexture_RW(renderer, img, 0); + if(!texture) + { + SDL_FreeRW(img); + fprintf(stderr, "Problem while loading the image: (%s).\n", argv[1]); + return 1; + } + + SDL_FreeRW(img); + + if(handle_events()) + { + fprintf(stderr, "Event handling exception.\n"); + return 1; + } + + return 0; +} + +int render(double zoom, double move_x, double move_y) +{ + SDL_Rect src = {0}; + SDL_Rect dst = {0}; + int screen_h, screen_w; + + SDL_RenderClear(renderer); + SDL_QueryTexture(texture, NULL, NULL, &src.w , &src.h); + + DBG("\nsrc w: %d h: %d x: %d y: %d\n", src.w, src.h, src.x, src.y); + + SDL_GetWindowSize(window, &dst.w, &dst.h); + screen_h = dst.h; + screen_w = dst.w; + + DBG("scr w: %d h: %d\n", screen_w, screen_h); + + /* APPLY ZOOM */ + dst.h *= zoom; + dst.w *= zoom; + + DBG("zoom: %f\n", zoom); + + /* REVERT IMAGE FILL */ + double ratio = (double) src.w / src.h; + if(dst.h >= dst.w / ratio) + dst.h = dst.w / ratio; + else + dst.w = ratio * dst.h; + + /* CENTER IN SCREEN */ + dst.x = (screen_w - dst.w) / 2; + dst.y = (screen_h - dst.h) / 2; + + DBG("dst w: %d h: %d x: %d y: %d\n\n", dst.w, dst.h, dst.x, dst.y); + + /* APPLY MOVE */ + dst.x -= move_x * dst.w; + dst.y -= move_y * dst.h; + + DBG("Moved by x_perc: %f y_perc: %f\n", move_x, move_y); + + SDL_RenderCopy(renderer, texture, &src, &dst); + SDL_RenderPresent(renderer); + + return 0; +} + +int handle_events() +{ + SDL_Event event; + + double zoom_multiplier = 0.1; // 10% + double move_multipler = 0.1; // 10% + + double zoom = 1.0; // 100% initially + double move_x = 0.0; // initial x pos (centered) + double move_y = 0.0; // initial y pos (centered) + + while(SDL_WaitEvent(&event)) + { + //DBG("Event: 0x%x\n", event.type); + switch(event.type) + { + case SDL_KEYDOWN: + switch(event.key.keysym.sym) + { + case '+': // zoom in + case 61: // + + zoom += zoom_multiplier; + render(zoom, move_x, move_y); + break; + case '-': // zoom out + zoom -= zoom - zoom_multiplier < 0 ? 0 : zoom_multiplier; + render(zoom, move_x, move_y); + break; + case 1073741906: // up arrow - move up + move_y -= move_multipler / zoom; + render(zoom, move_x, move_y); + break; + case 1073741905: // down arrow - move down + move_y += move_multipler / zoom; + render(zoom, move_x, move_y); + break; + case 1073741904: // left arrow - move left + move_x -= move_multipler / zoom; + render(zoom, move_x, move_y); + break; + case 1073741903: // right arrow - move right + move_x += move_multipler / zoom; + render(zoom, move_x, move_y); + break; + case 'q': + exit(0); + } + break; + case SDL_WINDOWEVENT: + render(zoom, move_x, move_y); + break; + case SDL_QUIT: + exit(0); + } + } + + return 1; +} + +void cleanup() +{ + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + IMG_Quit(); + SDL_Quit(); +} |