commit 6ac1850fa404420f18bcea62c5cefcfd7d575a1a
parent ab4ae60ad89cba4cca0d2f9b802628358fefaf0a
Author: lumidify <nobody@lumidify.org>
Date: Tue, 21 Sep 2021 15:45:59 +0200
Allow Imlib2 cache size to be controlled with command line argument
Diffstat:
2 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/croptool.1 b/croptool.1
@@ -51,6 +51,11 @@ Default: #000000.
.It Fl s Ar color
Set the secondary color for the cropping rectangle.
Default: #FFFFFF.
+.It Fl z Ar size
+Set the Imlib2 in-memory cache to
+.Ar size
+MiB (valid values: 0-1024).
+Default: 4.
.El
.Sh OUTPUT FORMAT
The cropping commands for each image are output using the format given by
diff --git a/croptool.c b/croptool.c
@@ -57,6 +57,8 @@ static short SELECTION_REDRAW = 1;
%f: Filename of image.
*/
static const char *CMD_FORMAT = "croptool_crop %wx%h+%l+%t '%f'";
+/* Size of Imlib2 in-memory cache in MiB */
+static int CACHE_SIZE = 4;
extern char *optarg;
extern int optind;
@@ -159,7 +161,7 @@ static void button_release(void);
static void button_press(XEvent event);
static void key_press(XEvent event);
static void queue_update(int x, int y, int w, int h);
-static int parse_small_positive_int(const char *str, int *value);
+static int parse_int(const char *str, int min, int max, int *value);
static void
usage(void) {
@@ -172,7 +174,7 @@ int
main(int argc, char *argv[]) {
char c;
- while ((c = getopt(argc, argv, "f:w:c:mrp:s:")) != -1) {
+ while ((c = getopt(argc, argv, "f:w:c:mrp:s:z:")) != -1) {
switch (c) {
case 'f':
CMD_FORMAT = optarg;
@@ -190,17 +192,23 @@ main(int argc, char *argv[]) {
SELECTION_COLOR2 = optarg;
break;
case 'c':
- if (parse_small_positive_int(optarg, &COLLISION_PADDING)) {
+ if (parse_int(optarg, 1, 99, &COLLISION_PADDING)) {
fprintf(stderr, "Invalid collision padding.\n");
exit(1);
}
break;
case 'w':
- if (parse_small_positive_int(optarg, &LINE_WIDTH)) {
+ if (parse_int(optarg, 1, 99, &LINE_WIDTH)) {
fprintf(stderr, "Invalid line width.\n");
exit(1);
}
break;
+ case 'z':
+ if (parse_int(optarg, 0, 1024, &CACHE_SIZE)) {
+ fprintf(stderr, "Invalid cache size.\n");
+ exit(1);
+ }
+ break;
default:
usage();
exit(1);
@@ -410,7 +418,13 @@ setup(int argc, char *argv[]) {
cursors.bottomright = XCreateFontCursor(state.dpy, XC_bottom_right_corner);
cursors.grab = XCreateFontCursor(state.dpy, XC_fleur);
- imlib_set_cache_size(2048 * 2048);
+ /* note: since CACHE_SIZE is <= 1024, this definitely fits in long */
+ long cs = (unsigned long long)CACHE_SIZE * 1024 * 1024;
+ if (cs > INT_MAX) {
+ fprintf(stderr, "Cache size would cause integer overflow.\n");
+ exit(1);
+ }
+ imlib_set_cache_size((int)cs);
imlib_set_color_usage(128);
imlib_context_set_dither(1);
imlib_context_set_display(state.dpy);
@@ -511,16 +525,19 @@ print_cmd(const char *filename, int x, int y, int w, int h, int dry_run) {
}
}
-/* Parses integer between 0 and 100 (non-inclusive).
+/* Parse integer between min and max (inclusive).
Returns 1 on error, 0 otherwise.
- The result is stored in *value. */
+ The result is stored in *value.
+ Based on OpenBSD's strtonum. */
static int
-parse_small_positive_int(const char *str, int *value) {
+parse_int(const char *str, int min, int max, int *value) {
char *end;
long l = strtol(str, &end, 10);
+ if (min > max)
+ return 1;
if (str == end || *end != '\0') {
return 1;
- } else if (l <= 0 || l >= 100 || ((l == LONG_MIN ||
+ } else if (l < min || l > max || ((l == LONG_MIN ||
l == LONG_MAX) && errno == ERANGE)) {
return 1;
}