diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/canvas.c | 22 | ||||
-rw-r--r-- | src/canvas.h | 8 | ||||
-rw-r--r-- | src/imv.c | 49 | ||||
-rw-r--r-- | src/viewport.c | 36 | ||||
-rw-r--r-- | src/viewport.h | 18 |
5 files changed, 124 insertions, 9 deletions
diff --git a/src/canvas.c b/src/canvas.c index c185c06..a1044d5 100644 --- a/src/canvas.c +++ b/src/canvas.c @@ -8,9 +8,9 @@ #include <cairo/cairo.h> #include <pango/pangocairo.h> #include <stdarg.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <stdbool.h> #ifdef IMV_BACKEND_LIBRSVG #include <librsvg/rsvg.h> @@ -204,7 +204,9 @@ static int convert_pixelformat(enum imv_pixelformat fmt) static void draw_bitmap(struct imv_canvas *canvas, struct imv_bitmap *bitmap, int bx, int by, double scale, - enum upscaling_method upscaling_method, bool cache_invalidated) + double rotation, bool mirrored, + enum upscaling_method upscaling_method, + bool cache_invalidated) { GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); @@ -249,6 +251,15 @@ static void draw_bitmap(struct imv_canvas *canvas, const int top = by; const int right = left + bitmap->width * scale; const int bottom = top + bitmap->height * scale; + const int center_x = left + bitmap->width * scale / 2; + const int center_y = top + bitmap->height * scale / 2; + + glTranslated(center_x, center_y, 0); + if (mirrored) { + glScaled(-1, 1, 1); + } + glRotated(-rotation, 0, 0, 1); + glTranslated(-center_x, -center_y, 0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -273,11 +284,14 @@ RsvgHandle *imv_image_get_svg(const struct imv_image *image); void imv_canvas_draw_image(struct imv_canvas *canvas, struct imv_image *image, int x, int y, double scale, - enum upscaling_method upscaling_method, bool cache_invalidated) + double rotation, bool mirrored, + enum upscaling_method upscaling_method, + bool cache_invalidated) { struct imv_bitmap *bitmap = imv_image_get_bitmap(image); if (bitmap) { - draw_bitmap(canvas, bitmap, x, y, scale, upscaling_method, cache_invalidated); + draw_bitmap(canvas, bitmap, x, y, scale, rotation, mirrored, + upscaling_method, cache_invalidated); return; } diff --git a/src/canvas.h b/src/canvas.h index fc043e5..255c10c 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -1,8 +1,8 @@ -#include <stdbool.h> - #ifndef IMV_CANVAS_H #define IMV_CANVAS_H +#include <stdbool.h> + struct imv_canvas; struct imv_image; @@ -48,6 +48,8 @@ void imv_canvas_draw(struct imv_canvas *canvas); /* Blit the given image to the current OpenGL framebuffer */ void imv_canvas_draw_image(struct imv_canvas *canvas, struct imv_image *image, int x, int y, double scale, - enum upscaling_method upscaling_method, bool cache_invalidated); + double rotation, bool mirrored, + enum upscaling_method upscaling_method, + bool cache_invalidated); #endif @@ -179,6 +179,9 @@ static void command_next(struct list *args, const char *argstr, void *data); static void command_prev(struct list *args, const char *argstr, void *data); static void command_goto(struct list *args, const char *argstr, void *data); static void command_zoom(struct list *args, const char *argstr, void *data); +static void command_rotate(struct list *args, const char *argstr, void *data); +static void command_rotate_to(struct list *args, const char *argstr, void *data); +static void command_flip(struct list *args, const char *argstr, void *data); static void command_open(struct list *args, const char *argstr, void *data); static void command_close(struct list *args, const char *argstr, void *data); static void command_fullscreen(struct list *args, const char *argstr, void *data); @@ -497,6 +500,9 @@ struct imv *imv_create(void) imv_command_register(imv->commands, "prev", &command_prev); imv_command_register(imv->commands, "goto", &command_goto); imv_command_register(imv->commands, "zoom", &command_zoom); + imv_command_register(imv->commands, "rotate", &command_rotate); + imv_command_register(imv->commands, "rotate_to", &command_rotate_to); + imv_command_register(imv->commands, "flip", &command_flip); imv_command_register(imv->commands, "open", &command_open); imv_command_register(imv->commands, "close", &command_close); imv_command_register(imv->commands, "fullscreen", &command_fullscreen); @@ -1183,10 +1189,15 @@ static void render_window(struct imv *imv) /* draw our actual image */ if (imv->current_image) { int x, y; - double scale; + double scale, rotation; + bool mirrored; imv_viewport_get_offset(imv->view, &x, &y); imv_viewport_get_scale(imv->view, &scale); - imv_canvas_draw_image(imv->canvas, imv->current_image, x, y, scale, imv->upscaling_method, imv->cache_invalidated); + imv_viewport_get_rotation(imv->view, &rotation); + imv_viewport_get_mirrored(imv->view, &mirrored); + imv_canvas_draw_image(imv->canvas, imv->current_image, + x, y, scale, rotation, mirrored, + imv->upscaling_method, imv->cache_invalidated); } imv_canvas_clear(imv->canvas); @@ -1497,6 +1508,39 @@ static void command_zoom(struct list *args, const char *argstr, void *data) } } +static void command_rotate(struct list *args, const char *argstr, void *data) +{ + (void)argstr; + struct imv *imv = data; + if (args->len == 2) { + double degrees = strtod(args->items[1], NULL); + imv_viewport_rotate(imv->view, degrees); + } +} + +static void command_rotate_to(struct list *args, const char *argstr, void *data) +{ + (void)argstr; + struct imv *imv = data; + if (args->len == 2) { + double degrees = strtod(args->items[1], NULL); + imv_viewport_rotate_to(imv->view, degrees); + } +} + +static void command_flip(struct list *args, const char *argstr, void *data) +{ + (void)argstr; + struct imv *imv = data; + if (args->len == 2) { + if (!strcmp(args->items[1], "vertical")) { + imv_viewport_flip_v(imv->view); + } else if (!strcmp(args->items[1], "horizontal")) { + imv_viewport_flip_h(imv->view); + } + } +} + static void command_open(struct list *args, const char *argstr, void *data) { (void)argstr; @@ -1584,6 +1628,7 @@ static void command_reset(struct list *args, const char *argstr, void *data) (void)args; (void)argstr; struct imv *imv = data; + imv_viewport_rotate_to(imv->view, 0); imv->need_rescale = true; imv->need_redraw = true; } diff --git a/src/viewport.c b/src/viewport.c index c894f26..7cfb7db 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -1,9 +1,12 @@ #include "viewport.h" +#include <stdbool.h> #include <stdlib.h> struct imv_viewport { double scale; + double rotation; + bool mirrored; struct { int width, height; } window; /* window dimensions */ @@ -32,6 +35,8 @@ struct imv_viewport *imv_viewport_create(int window_width, int window_height, view->buffer.width = buffer_width; view->buffer.height = buffer_height; view->scale = 1; + view->rotation = 0; + view->mirrored = false; view->x = view->y = view->redraw = 0; view->pan_factor_x = view->pan_factor_y = 0.5; view->playing = 1; @@ -84,6 +89,20 @@ void imv_viewport_get_scale(struct imv_viewport *view, double *scale) } } +void imv_viewport_get_rotation(struct imv_viewport *view, double *rotation) +{ + if(rotation) { + *rotation = view->rotation; + } +} + +void imv_viewport_get_mirrored(struct imv_viewport *view, bool *mirrored) +{ + if(mirrored) { + *mirrored = view->mirrored; + } +} + void imv_viewport_set_default_pan_factor(struct imv_viewport *view, double pan_factor_x, double pan_factor_y) { view->pan_factor_x = pan_factor_x; @@ -177,6 +196,23 @@ void imv_viewport_zoom(struct imv_viewport *view, const struct imv_image *image, view->locked = 1; } +void imv_viewport_rotate(struct imv_viewport *view, double degrees) { + view->rotation += degrees; +} + +void imv_viewport_rotate_to(struct imv_viewport *view, double degrees) { + view->rotation = degrees; +} + +void imv_viewport_flip_h(struct imv_viewport *view) { + view->mirrored = !view->mirrored; +} + +void imv_viewport_flip_v(struct imv_viewport *view) { + view->mirrored = !view->mirrored; + view->rotation = -(180.0 - view->rotation); +} + void imv_viewport_center(struct imv_viewport *view, const struct imv_image *image) { const int image_width = imv_image_width(image); diff --git a/src/viewport.h b/src/viewport.h index 5e5bc24..417bf93 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -42,6 +42,12 @@ void imv_viewport_get_offset(struct imv_viewport *view, int *x, int *y); /* Fetch viewport scale */ void imv_viewport_get_scale(struct imv_viewport *view, double *scale); +/* Fetch viewport rotation */ +void imv_viewport_get_rotation(struct imv_viewport *view, double *rotation); + +/* Fetch viewport mirror status */ +void imv_viewport_get_mirrored(struct imv_viewport *view, bool *mirrored); + /* Set the default pan_factor factor for the x and y position */ void imv_viewport_set_default_pan_factor(struct imv_viewport *view, double pan_factor_x, double pan_factor_y); @@ -55,6 +61,18 @@ void imv_viewport_move(struct imv_viewport *view, int x, int y, void imv_viewport_zoom(struct imv_viewport *view, const struct imv_image *image, enum imv_zoom_source, int mouse_x, int mouse_y, int amount); +/* Rotate the view by the given number of degrees */ +void imv_viewport_rotate(struct imv_viewport *view, double degrees); + +/* Rotate the view to the given number of degrees */ +void imv_viewport_rotate_to(struct imv_viewport *view, double degrees); + +/* Flip horizontally (across vertical axis) */ +void imv_viewport_flip_h(struct imv_viewport *view); + +/* Flip vertically (across horizontal axis) */ +void imv_viewport_flip_v(struct imv_viewport *view); + /* Recenter the view to be in the middle of the image */ void imv_viewport_center(struct imv_viewport *view, const struct imv_image *image); |