about summary refs log tree commit diff
path: root/main.c
diff options
context:
space:
mode:
authorYour Name <you@example.com>2020-10-12 00:02:22 +0000
committerYour Name <you@example.com>2020-10-12 00:02:22 +0000
commit286f93b894864a8a2dbe9ca34a4c18fd456790b7 (patch)
tree0a2db90634366a43670a729cecec5844621de868 /main.c
downloadOSXIV-master.tar.gz
OSXIV-master.tar.bz2
OSXIV-master.zip
Initial Release HEAD master
Diffstat (limited to '')
-rw-r--r--main.c199
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();
+}