Fabian Specht: 1 Add absolue and relative zoom functionality 6 files changed, 116 insertions(+), 85 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~exec64/imv-devel/patches/47616/mbox | git am -3Learn more about email & git
--- .gitignore | 1 + CHANGELOG | 6 ++ doc/imv.1.txt | 7 ++- src/imv.c | 24 +++++++- src/viewport.c | 156 ++++++++++++++++++++++++------------------------- src/viewport.h | 7 ++- 6 files changed, 116 insertions(+), 85 deletions(-) diff --git a/.gitignore b/.gitignore index b022387..a766ed3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ imv *.o test_* build/ +.cache/ diff --git a/CHANGELOG b/CHANGELOG index a1daf78..a5d125c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,12 @@ imv Changelog ============= +unversioned +----------- + +* Changed zoom to set absolute values +* old zoom command is now 'zoom_rel' + v4.4.0 - 2023-01-18 ------------------- diff --git a/doc/imv.1.txt b/doc/imv.1.txt index b0dfbf7..8de8cfb 100644 --- a/doc/imv.1.txt +++ b/doc/imv.1.txt @@ -99,10 +99,15 @@ Commands can be entered by pressing *:*. imv supports the following commands: Aliased to 'g'. *zoom* <amount|'actual'>:: - Zoom into the image by the given amount. Negative values zoom out. + Zoom into the image with the given amount in percent. 'actual' resets the zoom to 100%, showing the image at its actual size. Aliased to 'z'. +*zoom_rel* <amount|'actual'>:: + Zoom into the image by the given amount. Negative values zoom out. + 'actual' resets the zoom to 100%, showing the image at its actual size. + Aliased to 'zr'. + *rotate* <'to'|'by'> <angle>:: Rotate image clockwise by/to the given amount in degrees. diff --git a/src/imv.c b/src/imv.c index bca52fd..b20c4d8 100644 --- a/src/imv.c +++ b/src/imv.c @@ -200,6 +200,7 @@ 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_zoom_rel(struct list *args, const char *argstr, void *data); static void command_rotate(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); @@ -466,7 +467,7 @@ static void event_handler(void *data, const struct imv_event *e) double x, y; imv_window_get_mouse_position(imv->window, &x, &y); imv_viewport_zoom(imv->view, imv->current_image, IMV_ZOOM_MOUSE, - x, y, -e->data.mouse_scroll.dy); + IMV_ZOOM_RELATIVE, x, y, -e->data.mouse_scroll.dy); } break; case IMV_EVENT_CUSTOM: @@ -568,6 +569,7 @@ 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, "zoom_rel", &command_zoom_rel); imv_command_register(imv->commands, "rotate", &command_rotate); imv_command_register(imv->commands, "flip", &command_flip); imv_command_register(imv->commands, "open", &command_open); @@ -590,6 +592,7 @@ struct imv *imv_create(void) imv_command_alias(imv->commands, "p", "prev"); imv_command_alias(imv->commands, "g", "goto"); imv_command_alias(imv->commands, "z", "zoom"); + imv_command_alias(imv->commands, "zr", "zoom_rel"); imv_command_alias(imv->commands, "o", "open"); imv_command_alias(imv->commands, "bg", "background"); imv_command_alias(imv->commands, "ss", "slideshow"); @@ -1712,7 +1715,24 @@ static void command_zoom(struct list *args, const char *argstr, void *data) imv_viewport_scale_to_actual(imv->view, imv->current_image); } else { long int amount = strtol(args->items[1], NULL, 10); - imv_viewport_zoom(imv->view, imv->current_image, IMV_ZOOM_KEYBOARD, 0, 0, amount); + imv_viewport_zoom(imv->view, imv->current_image, + IMV_ZOOM_KEYBOARD, IMV_ZOOM_ABSOLUTE, 0, 0, amount); + } + } +} + +static void command_zoom_rel(struct list *args, const char *argstr, void *data) +{ + (void)argstr; + struct imv *imv = data; + if (args->len == 2) { + const char *str = args->items[1]; + if (!strcmp(str, "actual")) { + imv_viewport_scale_to_actual(imv->view, imv->current_image); + } else { + long int amount = strtol(args->items[1], NULL, 10); + imv_viewport_zoom(imv->view, imv->current_image, + IMV_ZOOM_KEYBOARD, IMV_ZOOM_RELATIVE, 0, 0, amount); } } } diff --git a/src/viewport.c b/src/viewport.c index 095bf71..32d59c2 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -1,8 +1,8 @@ #include "viewport.h" +#include <math.h> #include <stdbool.h> #include <stdlib.h> -#include <math.h> struct imv_viewport { double scale; @@ -21,15 +21,13 @@ struct imv_viewport { int locked; }; -static void input_xy_to_render_xy(struct imv_viewport *view, int *x, int *y) -{ +static void input_xy_to_render_xy(struct imv_viewport *view, int *x, int *y) { *x *= view->buffer.width / view->window.width; *y *= view->buffer.height / view->window.height; } struct imv_viewport *imv_viewport_create(int window_width, int window_height, - int buffer_width, int buffer_height) -{ + int buffer_width, int buffer_height) { struct imv_viewport *view = malloc(sizeof *view); view->window.width = window_width; view->window.height = window_height; @@ -45,74 +43,64 @@ struct imv_viewport *imv_viewport_create(int window_width, int window_height, return view; } -void imv_viewport_free(struct imv_viewport *view) -{ - free(view); -} +void imv_viewport_free(struct imv_viewport *view) { free(view); } -void imv_viewport_set_playing(struct imv_viewport *view, bool playing) -{ +void imv_viewport_set_playing(struct imv_viewport *view, bool playing) { view->playing = playing; } -bool imv_viewport_is_playing(struct imv_viewport *view) -{ +bool imv_viewport_is_playing(struct imv_viewport *view) { return view->playing; } -void imv_viewport_toggle_playing(struct imv_viewport *view) -{ +void imv_viewport_toggle_playing(struct imv_viewport *view) { view->playing = !view->playing; } -void imv_viewport_scale_to_actual(struct imv_viewport *view, const struct imv_image *image) -{ +void imv_viewport_scale_to_actual(struct imv_viewport *view, + const struct imv_image *image) { view->scale = 1; view->redraw = 1; view->locked = 1; imv_viewport_center(view, image); } -void imv_viewport_get_offset(struct imv_viewport *view, int *x, int *y) -{ - if(x) { +void imv_viewport_get_offset(struct imv_viewport *view, int *x, int *y) { + if (x) { *x = view->x; } - if(y) { + if (y) { *y = view->y; } } -void imv_viewport_get_scale(struct imv_viewport *view, double *scale) -{ - if(scale) { +void imv_viewport_get_scale(struct imv_viewport *view, double *scale) { + if (scale) { *scale = view->scale; } } -void imv_viewport_get_rotation(struct imv_viewport *view, double *rotation) -{ - if(rotation) { +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) { +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) -{ +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; view->pan_factor_y = pan_factor_y; } void imv_viewport_move(struct imv_viewport *view, int x, int y, - const struct imv_image *image) -{ + const struct imv_image *image) { input_xy_to_render_xy(view, &x, &y); view->x += x; view->y += y; @@ -134,9 +122,13 @@ void imv_viewport_move(struct imv_viewport *view, int x, int y, } } +/* zoom is specified through the given amount which is either applied as an + * absolue or relative value depending on the value of type + */ + void imv_viewport_zoom(struct imv_viewport *view, const struct imv_image *image, - enum imv_zoom_source src, int mouse_x, int mouse_y, int amount) -{ + enum imv_zoom_source src, enum imv_zoom_type type, + int mouse_x, int mouse_y, int amount) { double prev_scale = view->scale; int x, y; @@ -144,7 +136,7 @@ void imv_viewport_zoom(struct imv_viewport *view, const struct imv_image *image, const int image_height = imv_image_height(image); /* x and y coordinates are relative to the image */ - if(src == IMV_ZOOM_MOUSE) { + if (src == IMV_ZOOM_MOUSE) { input_xy_to_render_xy(view, &mouse_x, &mouse_y); x = mouse_x - view->x; y = mouse_y - view->y; @@ -155,35 +147,41 @@ void imv_viewport_zoom(struct imv_viewport *view, const struct imv_image *image, const int scaled_width = image_width * view->scale; const int scaled_height = image_height * view->scale; - const int ic_x = view->x + scaled_width/2; - const int ic_y = view->y + scaled_height/2; - const int wc_x = view->buffer.width/2; - const int wc_y = view->buffer.height/2; - const double scale_factor = pow(1.04, amount); - view->scale *= scale_factor; + const int ic_x = view->x + scaled_width / 2; + const int ic_y = view->y + scaled_height / 2; + + const int wc_x = view->buffer.width / 2; + const int wc_y = view->buffer.height / 2; + + if (type == IMV_ZOOM_ABSOLUTE) { + view->scale = amount * 0.01; + } else { + const double scale_factor = pow(1.04, amount); + view->scale *= scale_factor; + } const double min_scale = 0.1; const double max_scale = 100; - if(view->scale > max_scale) { + if (view->scale > max_scale) { view->scale = max_scale; } else if (view->scale < min_scale) { view->scale = min_scale; } - if(view->scale < prev_scale) { - if(scaled_width < view->buffer.width) { - x = scaled_width/2 - (ic_x - wc_x)*2; + if (view->scale < prev_scale) { + if (scaled_width < view->buffer.width) { + x = scaled_width / 2 - (ic_x - wc_x) * 2; } - if(scaled_height < view->buffer.height) { - y = scaled_height/2 - (ic_y - wc_y)*2; + if (scaled_height < view->buffer.height) { + y = scaled_height / 2 - (ic_y - wc_y) * 2; } } else { - if(scaled_width < view->buffer.width) { - x = scaled_width/2; + if (scaled_width < view->buffer.width) { + x = scaled_width / 2; } - if(scaled_height < view->buffer.height) { - y = scaled_height/2; + if (scaled_height < view->buffer.height) { + y = scaled_height / 2; } } @@ -219,8 +217,8 @@ void imv_viewport_reset_transform(struct imv_viewport *view) { view->rotation = 0; } -void imv_viewport_center(struct imv_viewport *view, const struct imv_image *image) -{ +void imv_viewport_center(struct imv_viewport *view, + const struct imv_image *image) { const int image_width = imv_image_width(image); const int image_height = imv_image_height(image); @@ -245,14 +243,15 @@ void imv_viewport_center(struct imv_viewport *view, const struct imv_image *imag view->redraw = 1; } -void imv_viewport_scale_to_window(struct imv_viewport *view, const struct imv_image *image) -{ +void imv_viewport_scale_to_window(struct imv_viewport *view, + const struct imv_image *image) { const int image_width = imv_image_width(image); const int image_height = imv_image_height(image); - const double window_aspect = (double)view->buffer.width / (double)view->buffer.height; + const double window_aspect = + (double)view->buffer.width / (double)view->buffer.height; const double image_aspect = (double)image_width / (double)image_height; - if(window_aspect > image_aspect) { + if (window_aspect > image_aspect) { /* Image will become too tall before it becomes too wide */ view->scale = (double)view->buffer.height / (double)image_height; } else { @@ -264,15 +263,16 @@ void imv_viewport_scale_to_window(struct imv_viewport *view, const struct imv_im view->locked = 0; } -void imv_viewport_crop_to_window(struct imv_viewport *view, const struct imv_image *image) -{ +void imv_viewport_crop_to_window(struct imv_viewport *view, + const struct imv_image *image) { const int image_width = imv_image_width(image); const int image_height = imv_image_height(image); - const double window_aspect = (double)view->buffer.width / (double)view->buffer.height; + const double window_aspect = + (double)view->buffer.width / (double)view->buffer.height; const double image_aspect = (double)image_width / (double)image_height; /* Scale the image so that it fills the whole window */ - if(window_aspect > image_aspect) { + if (window_aspect > image_aspect) { view->scale = (double)view->buffer.width / (double)image_width; } else { view->scale = (double)view->buffer.height / (double)image_height; @@ -282,17 +282,15 @@ void imv_viewport_crop_to_window(struct imv_viewport *view, const struct imv_ima view->locked = 0; } -void imv_viewport_set_redraw(struct imv_viewport *view) -{ - view->redraw = 1; -} +void imv_viewport_set_redraw(struct imv_viewport *view) { view->redraw = 1; } -void imv_viewport_rescale(struct imv_viewport *view, const struct imv_image *image, +void imv_viewport_rescale(struct imv_viewport *view, + const struct imv_image *image, enum scaling_mode scaling_mode) { if (scaling_mode == SCALING_NONE || - (scaling_mode == SCALING_DOWN - && view->buffer.width > imv_image_width(image) - && view->buffer.height > imv_image_height(image))) { + (scaling_mode == SCALING_DOWN && + view->buffer.width > imv_image_width(image) && + view->buffer.height > imv_image_height(image))) { imv_viewport_scale_to_actual(view, image); } else if (scaling_mode == SCALING_CROP) { imv_viewport_crop_to_window(view, image); @@ -301,19 +299,17 @@ void imv_viewport_rescale(struct imv_viewport *view, const struct imv_image *ima } } -void imv_viewport_update(struct imv_viewport *view, - int window_width, int window_height, - int buffer_width, int buffer_height, +void imv_viewport_update(struct imv_viewport *view, int window_width, + int window_height, int buffer_width, int buffer_height, struct imv_image *image, - enum scaling_mode scaling_mode) -{ + enum scaling_mode scaling_mode) { view->window.width = window_width; view->window.height = window_height; view->buffer.width = buffer_width; view->buffer.height = buffer_height; view->redraw = 1; - if(view->locked) { + if (view->locked) { return; } @@ -321,15 +317,13 @@ void imv_viewport_update(struct imv_viewport *view, imv_viewport_rescale(view, image, scaling_mode); } -int imv_viewport_needs_redraw(struct imv_viewport *view) -{ +int imv_viewport_needs_redraw(struct imv_viewport *view) { int redraw = 0; - if(view->redraw) { + if (view->redraw) { redraw = 1; view->redraw = 0; } return redraw; } - /* vim:set ts=2 sts=2 sw=2 et: */ diff --git a/src/viewport.h b/src/viewport.h index a24113c..2244715 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -20,6 +20,11 @@ enum imv_zoom_source { IMV_ZOOM_KEYBOARD }; +enum imv_zoom_type { + IMV_ZOOM_ABSOLUTE, + IMV_ZOOM_RELATIVE +}; + /* Creates an instance of imv_viewport */ struct imv_viewport *imv_viewport_create(int window_width, int window_height, int buffer_width, int buffer_height); @@ -59,7 +64,7 @@ void imv_viewport_move(struct imv_viewport *view, int x, int y, /* Zoom the view by the given amount. imv_image* is used to get the image * dimensions */ 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); + enum imv_zoom_source, enum imv_zoom_type, int mouse_x, int mouse_y, int amount); /* Rotate the view by the given number of degrees */ void imv_viewport_rotate_by(struct imv_viewport *view, double degrees); -- 2.43.0