croptool

Image cropping tool
git clone git://lumidify.org/croptool.git (fast, but not encrypted)
git clone https://lumidify.org/git/croptool.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 60095c0878b2e20accd0412419e3472a00b6ef6a
parent bec9b79f432571ee583f444a974617abda52f774
Author: lumidify <nobody@lumidify.org>
Date:   Sat,  6 Mar 2021 11:42:48 +0100

Reformat code a bit

Diffstat:
Mcroptool.c | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 100 insertions(+), 30 deletions(-)

diff --git a/croptool.c b/croptool.c @@ -235,7 +235,10 @@ mainloop(void) { break; case ConfigureNotify: if (RESIZE_REDRAW) - resize_window(event.xconfigure.width, event.xconfigure.height); + resize_window( + event.xconfigure.width, + event.xconfigure.height + ); break; case ButtonPress: if (event.xbutton.button == Button1) @@ -299,10 +302,14 @@ setup(int argc, char *argv[]) { if (XdbeQueryExtension(state.dpy, &major, &minor)) { int num_screens = 1; Drawable screens[] = { DefaultRootWindow(state.dpy) }; - XdbeScreenVisualInfo *info = XdbeGetVisualInfo(state.dpy, screens, &num_screens); + XdbeScreenVisualInfo *info = XdbeGetVisualInfo( + state.dpy, screens, &num_screens + ); if (!info || num_screens < 1 || info->count < 1) { - fprintf(stderr, "Warning: No visuals support Xdbe, " - "double buffering disabled.\n"); + fprintf(stderr, + "Warning: No visuals support Xdbe, " + "double buffering disabled.\n" + ); } else { XVisualInfo xvisinfo_templ; xvisinfo_templ.visualid = info->visinfo[0].visual; @@ -315,9 +322,10 @@ setup(int argc, char *argv[]) { &xvisinfo_templ, &matches ); if (!xvisinfo_match || matches < 1) { - fprintf(stderr, "Warning: Couldn't match a Visual " - "with double buffering, double " - "buffering disabled.\n"); + fprintf(stderr, + "Warning: Couldn't match a Visual with " + "double buffering, double buffering disabled.\n" + ); } else { state.vis = xvisinfo_match->visual; state.depth = xvisinfo_match->depth; @@ -334,6 +342,8 @@ setup(int argc, char *argv[]) { memset(&attrs, 0, sizeof(attrs)); attrs.background_pixel = BlackPixel(state.dpy, state.screen); attrs.colormap = state.cm; + /* this causes the window contents to be kept + * when it is resized, leading to less flicker */ attrs.bit_gravity = NorthWestGravity; state.win = XCreateWindow(state.dpy, DefaultRootWindow(state.dpy), 0, 0, state.window_w, state.window_h, 0, state.depth, @@ -341,7 +351,9 @@ setup(int argc, char *argv[]) { #ifndef NODB if (state.db_enabled) { - state.back_buf = XdbeAllocateBackBufferName(state.dpy, state.win, XdbeCopied); + state.back_buf = XdbeAllocateBackBufferName( + state.dpy, state.win, XdbeCopied + ); state.drawable = state.back_buf; } else { state.drawable = state.win; @@ -365,7 +377,11 @@ setup(int argc, char *argv[]) { } XAllocColor(state.dpy, state.cm, &state.col2); - XSelectInput(state.dpy, state.win, StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask); + XSelectInput( + state.dpy, state.win, + StructureNotifyMask | KeyPressMask | ButtonPressMask | + ButtonReleaseMask | PointerMotionMask | ExposureMask + ); state.wm_delete_msg = XInternAtom(state.dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols(state.dpy, state.win, &state.wm_delete_msg, 1); @@ -452,7 +468,9 @@ print_cmd(const char *filename, int x, int y, int w, int h) { printf("%s", filename); percent = 0; } else if (percent) { - fprintf(stderr, "Warning: Unknown substitution '%c' in format string.\n", *c); + fprintf(stderr, + "Warning: Unknown substitution '%c' in format string.\n", *c + ); printf("%%%c", *c); percent = 0; } else { @@ -482,6 +500,7 @@ parse_small_positive_int(const char *str, int *value) { return 0; } +/* queue a part of the image for redrawing */ static void queue_update(int x, int y, int w, int h) { if (state.cur_selection < 0 || !state.selections[state.cur_selection].valid) @@ -492,7 +511,8 @@ queue_update(int x, int y, int w, int h) { state.updates = imlib_update_append_rect( state.updates, x, y, w + x > sel->scaled_w ? sel->scaled_w - x : w, - h + y > sel->scaled_h ? sel->scaled_h - y : h); + h + y > sel->scaled_h ? sel->scaled_h - y : h + ); } static void @@ -500,12 +520,20 @@ redraw(void) { Imlib_Image buffer; Imlib_Updates current_update; if (!state.cur_image || state.cur_selection < 0) { + /* clear the window completely */ XSetForeground(state.dpy, state.gc, BlackPixel(state.dpy, state.screen)); - XFillRectangle(state.dpy, state.drawable, state.gc, 0, 0, state.window_w, state.window_h); + XFillRectangle( + state.dpy, state.drawable, state.gc, + 0, 0, state.window_w, state.window_h + ); goto swap_buffers; } + + /* draw the parts of the image that need to be redrawn */ struct Selection *sel = &state.selections[state.cur_selection]; - state.updates = imlib_updates_merge_for_rendering(state.updates, sel->scaled_w, sel->scaled_h); + state.updates = imlib_updates_merge_for_rendering( + state.updates, sel->scaled_w, sel->scaled_h + ); for (current_update = state.updates; current_update; current_update = imlib_updates_get_next(current_update)) { int up_x, up_y, up_w, up_h; @@ -527,8 +555,14 @@ redraw(void) { /* wipe the black area around the image */ XSetForeground(state.dpy, state.gc, BlackPixel(state.dpy, state.screen)); - XFillRectangle(state.dpy, state.drawable, state.gc, 0, sel->scaled_h, sel->scaled_w, state.window_h - sel->scaled_h); - XFillRectangle(state.dpy, state.drawable, state.gc, sel->scaled_w, 0, state.window_w - sel->scaled_w, state.window_h); + XFillRectangle( + state.dpy, state.drawable, state.gc, + 0, sel->scaled_h, sel->scaled_w, state.window_h - sel->scaled_h + ); + XFillRectangle( + state.dpy, state.drawable, state.gc, + sel->scaled_w, 0, state.window_w - sel->scaled_w, state.window_h + ); /* draw the rectangle */ struct Rect rect = sel->rect; @@ -536,7 +570,10 @@ redraw(void) { XColor col = state.cur_col == 1 ? state.col1 : state.col2; XSetForeground(state.dpy, state.gc, col.pixel); sort_coordinates(&rect.x0, &rect.y0, &rect.x1, &rect.y1); - XDrawRectangle(state.dpy, state.drawable, state.gc, rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0); + XDrawRectangle( + state.dpy, state.drawable, state.gc, + rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0 + ); } swap_buffers: @@ -561,6 +598,8 @@ swap(int *a, int *b) { *b = tmp; } +/* sort rectangle coordinates into their canonical + * form so *x1 - *x0 >= 0 and *y1 - *y0 >= 0 */ static void sort_coordinates(int *x0, int *y0, int *x1, int *y1) { if (*x0 > *x1) @@ -683,7 +722,7 @@ button_release(void) { state.lock_x = 0; state.lock_y = 0; /* redraw everything if automatic redrawing of the rectangle - is disabled (so it's redrawn when the mouse is released */ + is disabled (so it's redrawn when the mouse is released) */ if (!SELECTION_REDRAW) queue_update(0, 0, state.window_w, state.window_h); } @@ -701,9 +740,10 @@ resize_window(int w, int h) { get_scaled_size(sel->orig_w, sel->orig_h, &actual_w, &actual_h); if (actual_w != sel->scaled_w) { if (sel->rect.x0 != -200) { - /* If there is a selection, we need to convert it to the new scale. - * This only takes width into account because the aspect ratio - * should have been preserved anyways */ + /* If there is a selection, we need to convert it to + * the new scale. This only takes width into account + * because the aspect ratio should have been preserved + * anyways */ double scale = (double)actual_w / sel->scaled_w; sel->rect.x0 = round(sel->rect.x0 * scale); sel->rect.y0 = round(sel->rect.y0 * scale); @@ -716,6 +756,10 @@ resize_window(int w, int h) { } } +/* queue the redrawing of a rectangular area on the image - + * this queues four updates, one for each side of the rectangle, + * with the width or height (depending on which side) of the + * rectangle being determined by the configured line width */ static void queue_rectangle_redraw(int x0, int y0, int x1, int y1) { sort_coordinates(&x0, &y0, &x1, &y1); @@ -809,6 +853,7 @@ set_selection( sel->scaled_h = scaled_h; } +/* get the scaled size of an image based on the current window size */ static void get_scaled_size(int orig_w, int orig_h, int *scaled_w, int *scaled_h) { double scale_w, scale_h; @@ -826,10 +871,20 @@ get_scaled_size(int orig_w, int orig_h, int *scaled_w, int *scaled_h) { } } +/* change the shown image + * new_selection is the index of the new selection + * copy_box determines whether the cropping rectangle of the current + * selection should be copied (i.e. this is a true value when return + * is pressed) */ static void change_picture(Imlib_Image new_image, int new_selection, int copy_box) { int orig_w, orig_h, actual_w, actual_h; - XSetStandardProperties(state.dpy, state.win, state.filenames[new_selection], NULL, None, NULL, 0, NULL); + /* set window title to filename */ + XSetStandardProperties( + state.dpy, state.win, + state.filenames[new_selection], + NULL, None, NULL, 0, NULL + ); if (state.cur_image) { imlib_context_set_image(state.cur_image); imlib_free_image(); @@ -846,15 +901,23 @@ change_picture(Imlib_Image new_image, int new_selection, int copy_box) { struct Selection *sel = &state.selections[state.cur_selection]; if (copy_box && old_selection >= 0 && old_selection < state.num_files) { struct Selection *old = &state.selections[old_selection]; - set_selection(sel, old->rect.x0, old->rect.y0, old->rect.x1, old->rect.y1, - orig_w, orig_h, actual_w, actual_h); + set_selection( + sel, + old->rect.x0, old->rect.y0, old->rect.x1, old->rect.y1, + orig_w, orig_h, actual_w, actual_h + ); } else if (!sel->valid) { - /* Just fill it with -200 so we can check later if it has been used yet */ - set_selection(sel, -200, -200, -200, -200, orig_w, orig_h, actual_w, actual_h); + /* Just fill it with -200 so we can check + * later if it has been used yet */ + set_selection( + sel, + -200, -200, -200, -200, + orig_w, orig_h, actual_w, actual_h + ); } else if (sel->rect.x0 != -200 && actual_w != sel->scaled_w) { - /* If there is a selection, we need to convert it to the new scale. - * This only takes width into account because the aspect ratio - * should have been preserved anyways */ + /* If there is a selection, we need to convert it to the + * new scale. This only takes width into account because + * the aspect ratio should have been preserved anyways */ double scale = (double)actual_w / sel->scaled_w; sel->rect.x0 = round(sel->rect.x0 * scale); sel->rect.y0 = round(sel->rect.y0 * scale); @@ -867,6 +930,8 @@ change_picture(Imlib_Image new_image, int new_selection, int copy_box) { queue_update(0, 0, sel->scaled_w, sel->scaled_h); } +/* show the next image in the argument list - unloadable files are skipped + * copy_box determines whether the current selection is copied */ static void next_picture(int copy_box) { if (state.cur_selection + 1 >= state.num_files) @@ -876,7 +941,9 @@ next_picture(int copy_box) { /* loop until we find a loadable file */ while (!tmp_image && tmp_cur_selection + 1 < state.num_files) { tmp_cur_selection++; - tmp_image = imlib_load_image_immediately(state.filenames[tmp_cur_selection]); + tmp_image = imlib_load_image_immediately( + state.filenames[tmp_cur_selection] + ); if (!tmp_image) { fprintf(stderr, "Warning: Unable to load image '%s'.\n", state.filenames[tmp_cur_selection]); @@ -893,6 +960,7 @@ next_picture(int copy_box) { change_picture(tmp_image, tmp_cur_selection, copy_box); } +/* show the previous image in the argument list - unloadable files are skipped */ static void last_picture(void) { if (state.cur_selection <= 0) @@ -902,7 +970,9 @@ last_picture(void) { /* loop until we find a loadable file */ while (!tmp_image && tmp_cur_selection > 0) { tmp_cur_selection--; - tmp_image = imlib_load_image_immediately(state.filenames[tmp_cur_selection]); + tmp_image = imlib_load_image_immediately( + state.filenames[tmp_cur_selection] + ); if (!tmp_image) { fprintf(stderr, "Warning: Unable to load image '%s'.\n", state.filenames[tmp_cur_selection]);