Skip to content

Commit 6b47e41

Browse files
committed
improve zooming feature with natural logarithm
1 parent d65f3ba commit 6b47e41

6 files changed

Lines changed: 57 additions & 45 deletions

File tree

src/events.c

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ fehkey *feh_str_to_kb(char *action);
4040

4141
feh_event_handler *ev_handler[LASTEvent];
4242

43+
static const double zoom_rate = M_LN2 / 128.0;
44+
4345
static void feh_event_handle_ButtonPress(XEvent * ev);
4446
static void feh_event_handle_ButtonRelease(XEvent * ev);
4547
static void feh_event_handle_LeaveNotify(XEvent * ev);
@@ -242,29 +244,31 @@ static void feh_event_handle_ButtonPress(XEvent * ev)
242244
D(("click offset is %d,%d\n", ev->xbutton.x, ev->xbutton.y));
243245
winwid->click_offset_x = ev->xbutton.x;
244246
winwid->click_offset_y = ev->xbutton.y;
245-
winwid->old_zoom = winwid->zoom;
247+
winwid->zoom_old = round(log(winwid->zoom) / zoom_rate);
246248

247249
/* required to adjust the image position in zoom mode */
248250
winwid->im_click_offset_x = (winwid->click_offset_x
249-
- winwid->im_x) / winwid->old_zoom;
251+
- winwid->im_x) / winwid->zoom;
250252
winwid->im_click_offset_y = (winwid->click_offset_y
251-
- winwid->im_y) / winwid->old_zoom;
253+
- winwid->im_y) / winwid->zoom;
252254

253255
} else if (feh_is_bb(EVENT_zoom_in, button, state)) {
254256
D(("Zoom_In Button Press event\n"));
255257
D(("click offset is %d,%d\n", ev->xbutton.x, ev->xbutton.y));
258+
if (winwid->zoom >= ZOOM_MAX || opt.step_rate <= 0)
259+
return;
260+
256261
winwid->click_offset_x = ev->xbutton.x;
257262
winwid->click_offset_y = ev->xbutton.y;
258-
winwid->old_zoom = winwid->zoom;
259263

260264
/* required to adjust the image position in zoom mode */
261265
winwid->im_click_offset_x = (winwid->click_offset_x
262-
- winwid->im_x) / winwid->old_zoom;
266+
- winwid->im_x) / winwid->zoom;
263267
winwid->im_click_offset_y = (winwid->click_offset_y
264-
- winwid->im_y) / winwid->old_zoom;
268+
- winwid->im_y) / winwid->zoom;
265269

266270
/* copied from zoom_in, keyevents.c */
267-
winwid->zoom = winwid->zoom * opt.zoom_rate;
271+
winwid->zoom = exp(++winwid->zoom_step * opt.step_rate);
268272

269273
if (winwid->zoom > ZOOM_MAX)
270274
winwid->zoom = ZOOM_MAX;
@@ -281,18 +285,20 @@ static void feh_event_handle_ButtonPress(XEvent * ev)
281285
} else if (feh_is_bb(EVENT_zoom_out, button, state)) {
282286
D(("Zoom_Out Button Press event\n"));
283287
D(("click offset is %d,%d\n", ev->xbutton.x, ev->xbutton.y));
288+
if (winwid->zoom <= ZOOM_MIN || opt.step_rate <= 0)
289+
return;
290+
284291
winwid->click_offset_x = ev->xbutton.x;
285292
winwid->click_offset_y = ev->xbutton.y;
286-
winwid->old_zoom = winwid->zoom;
287293

288294
/* required to adjust the image position in zoom mode */
289295
winwid->im_click_offset_x = (winwid->click_offset_x
290-
- winwid->im_x) / winwid->old_zoom;
296+
- winwid->im_x) / winwid->zoom;
291297
winwid->im_click_offset_y = (winwid->click_offset_y
292-
- winwid->im_y) / winwid->old_zoom;
298+
- winwid->im_y) / winwid->zoom;
293299

294300
/* copied from zoom_out, keyevents.c */
295-
winwid->zoom = winwid->zoom / opt.zoom_rate;
301+
winwid->zoom = exp(--winwid->zoom_step * opt.step_rate);
296302

297303
if (winwid->zoom < ZOOM_MIN)
298304
winwid->zoom = ZOOM_MIN;
@@ -400,11 +406,14 @@ static void feh_event_handle_ButtonRelease(XEvent * ev)
400406
opt.mode = MODE_NORMAL;
401407
winwid->mode = MODE_NORMAL;
402408

403-
if ((feh_is_bb(EVENT_zoom, button, state))
404-
&& (ev->xbutton.x == winwid->click_offset_x)
405-
&& (ev->xbutton.y == winwid->click_offset_y)) {
406-
winwid->zoom = 1.0;
407-
winwidget_center_image(winwid);
409+
if ((feh_is_bb(EVENT_zoom, button, state))) {
410+
winwid->zoom_step = round(log(winwid->zoom) / opt.step_rate);
411+
if ((ev->xbutton.x == winwid->click_offset_x)
412+
&& (ev->xbutton.y == winwid->click_offset_y)) {
413+
winwid->zoom = 1.0;
414+
winwidget_center_image(winwid);
415+
} else
416+
winwidget_sanitise_offsets(winwid);
408417
} else
409418
winwidget_sanitise_offsets(winwid);
410419

@@ -543,14 +552,8 @@ static void feh_event_handle_MotionNotify(XEvent * ev)
543552

544553
winwid = winwidget_get_from_window(ev->xmotion.window);
545554
if (winwid) {
546-
if (ev->xmotion.x > winwid->click_offset_x)
547-
winwid->zoom = winwid->old_zoom + (
548-
((double) ev->xmotion.x - (double) winwid->click_offset_x)
549-
/ 128.0);
550-
else
551-
winwid->zoom = winwid->old_zoom - (
552-
((double) winwid->click_offset_x - (double) ev->xmotion.x)
553-
/ 128.0);
555+
int step = winwid->zoom_old + ev->xmotion.x - winwid->click_offset_x;
556+
winwid->zoom = exp(step * zoom_rate);
554557

555558
if (winwid->zoom < ZOOM_MIN)
556559
winwid->zoom = ZOOM_MIN;

src/keyevents.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -602,30 +602,36 @@ void feh_event_handle_generic(winwidget winwid, unsigned int state, KeySym keysy
602602
feh_event_invoke_action(winwid, 9);
603603
}
604604
else if (feh_is_kp(EVENT_zoom_in, state, keysym, button)) {
605-
winwid->old_zoom = winwid->zoom;
606-
winwid->zoom = winwid->zoom * opt.zoom_rate;
605+
if (winwid->zoom >= ZOOM_MAX || opt.step_rate <= 0)
606+
return;
607+
608+
double old_zoom = winwid->zoom;
609+
winwid->zoom = exp(++winwid->zoom_step * opt.step_rate);
607610

608611
if (winwid->zoom > ZOOM_MAX)
609612
winwid->zoom = ZOOM_MAX;
610613

611614
winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) /
612-
winwid->old_zoom * winwid->zoom);
615+
old_zoom * winwid->zoom);
613616
winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) /
614-
winwid->old_zoom * winwid->zoom);
617+
old_zoom * winwid->zoom);
615618
winwidget_sanitise_offsets(winwid);
616619
winwidget_render_image(winwid, 0, 0);
617620
}
618621
else if (feh_is_kp(EVENT_zoom_out, state, keysym, button)) {
619-
winwid->old_zoom = winwid->zoom;
620-
winwid->zoom = winwid->zoom / opt.zoom_rate;
622+
if (winwid->zoom <= ZOOM_MIN || opt.step_rate <= 0)
623+
return;
624+
625+
double old_zoom = winwid->zoom;
626+
winwid->zoom = exp(--winwid->zoom_step * opt.step_rate);
621627

622628
if (winwid->zoom < ZOOM_MIN)
623629
winwid->zoom = ZOOM_MIN;
624630

625631
winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) /
626-
winwid->old_zoom * winwid->zoom);
632+
old_zoom * winwid->zoom);
627633
winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) /
628-
winwid->old_zoom * winwid->zoom);
634+
old_zoom * winwid->zoom);
629635
winwidget_sanitise_offsets(winwid);
630636
winwidget_render_image(winwid, 0, 0);
631637
}

src/options.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void init_parse_options(int argc, char **argv)
6363
opt.font = NULL;
6464
opt.max_height = opt.max_width = UINT_MAX;
6565

66-
opt.zoom_rate = 1.25;
66+
opt.step_rate = M_LN2 / 3.0;
6767

6868
opt.start_list_at = NULL;
6969
opt.jump_on_resort = 1;
@@ -846,12 +846,11 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
846846
opt.x11_windowid = strtol(optarg, NULL, 0);
847847
break;
848848
case OPTION_zoom_step:
849-
opt.zoom_rate = atof(optarg);
850-
if ((opt.zoom_rate <= 0)) {
851-
weprintf("Zooming disabled due to --zoom-step=%f", opt.zoom_rate);
852-
opt.zoom_rate = 1.0;
849+
opt.step_rate = atof(optarg);
850+
if ((opt.step_rate <= 0)) {
851+
weprintf("Zooming disabled due to --zoom-step=%f", opt.step_rate);
853852
} else {
854-
opt.zoom_rate = 1 + ((float)opt.zoom_rate / 100);
853+
opt.step_rate = M_LN2 / opt.step_rate;
855854
}
856855
break;
857856
default:

src/options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ struct __fehoptions {
127127
int offset_y;
128128
int default_zoom;
129129
int zoom_mode;
130-
double zoom_rate;
130+
double step_rate;
131131
unsigned char adjust_reload;
132132
int xinerama_index;
133133
char *x11_class;

src/winwidget.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ static winwidget winwidget_allocate(void)
7777
ret->im_x = 0;
7878
ret->im_y = 0;
7979
ret->zoom = 1.0;
80-
ret->old_zoom = 1.0;
80+
ret->zoom_step = 0;
81+
ret->zoom_old = 0;
8182

8283
ret->click_offset_x = 0;
8384
ret->click_offset_y = 0;
@@ -494,6 +495,8 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)
494495
&& (!opt.default_zoom || required_zoom < winwid->zoom))
495496
winwid->zoom = required_zoom;
496497

498+
winwid->zoom_step = round(log(winwid->zoom) / opt.step_rate);
499+
497500
if (opt.offset_flags & XValue) {
498501
if (opt.offset_flags & XNegative) {
499502
winwid->im_x = winwid->w - (winwid->im_w * winwid->zoom) - opt.offset_x;
@@ -1065,20 +1068,20 @@ void feh_debug_print_winwid(winwidget w)
10651068
"h = %d\n" "im_w = %d\n" "im_h = %d\n" "im_angle = %f\n"
10661069
"type = %d\n" "had_resize = %d\n" "im = %p\n" "GC = %p\n"
10671070
"pixmap = %ld\n" "name = %s\n" "file = %p\n" "mode = %d\n"
1068-
"im_x = %d\n" "im_y = %d\n" "zoom = %f\n" "old_zoom = %f\n"
1069-
"click_offset_x = %d\n" "click_offset_y = %d\n"
1071+
"im_x = %d\n" "im_y = %d\n" "zoom = %f\n" "zoom_step = %d\n"
1072+
"zoom_old = %d" "click_offset_x = %d\n" "click_offset_y = %d\n"
10701073
"has_rotated = %d\n", (void *)w, w->win, w->w, w->h, w->im_w,
10711074
w->im_h, w->im_angle, w->type, w->had_resize, w->im, (void *)w->gc,
10721075
w->bg_pmap, w->name, (void *)w->file, w->mode, w->im_x, w->im_y,
1073-
w->zoom, w->old_zoom, w->click_offset_x, w->click_offset_y,
1076+
w->zoom, w->zoom_step, w->zoom_old, w->click_offset_x, w->click_offset_y,
10741077
w->has_rotated);
10751078
}
10761079

10771080
void winwidget_reset_image(winwidget winwid)
10781081
{
10791082
if (!opt.keep_zoom_vp) {
10801083
winwid->zoom = 1.0;
1081-
winwid->old_zoom = 1.0;
1084+
winwid->zoom_step = 0;
10821085
winwid->im_x = 0;
10831086
winwid->im_y = 0;
10841087
}

src/winwidget.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ struct __winwidget {
107107
* all the way up to INT_MAX (eww)
108108
*/
109109
double zoom;
110-
double old_zoom;
110+
int zoom_step;
111+
int zoom_old;
111112

112113
int click_offset_x;
113114
int click_offset_y;

0 commit comments

Comments
 (0)