aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands.c3
-rw-r--r--config.h7
-rw-r--r--image.c104
-rw-r--r--image.h13
-rw-r--r--main.c20
-rw-r--r--util.c13
-rw-r--r--util.h2
7 files changed, 126 insertions, 36 deletions
diff --git a/commands.c b/commands.c
index 50a3c2b..b0f7b08 100644
--- a/commands.c
+++ b/commands.c
@@ -41,6 +41,7 @@ extern int filecnt, fileidx;
extern int timo_cursor;
extern int timo_redraw;
+extern int timo_delay;
int it_quit(arg_t a) {
cleanup();
@@ -148,7 +149,7 @@ int it_last(arg_t a) {
}
int i_navigate_frame(arg_t a) {
- return img_change_frame(&img, (int) a);
+ return img_frame_navigate(&img, (int) a);
}
int it_move(arg_t a) {
diff --git a/config.h b/config.h
index a55ea18..07371c9 100644
--- a/config.h
+++ b/config.h
@@ -29,6 +29,13 @@ static const float zoom_levels[] = {
100.0, 150.0, 200.0, 400.0, 800.0
};
+/* default settings for gif images: */
+enum {
+ GIF_DELAY = 100, /* delay time (in ms) */
+ GIF_AUTOPLAY = 1, /* autoplay when loaded [0/1] */
+ GIF_LOOP = 0 /* endless loop [0/1] */
+};
+
#endif
#ifdef _THUMBS_CONFIG
diff --git a/image.c b/image.c
index 7c610a6..178ace3 100644
--- a/image.c
+++ b/image.c
@@ -32,6 +32,8 @@
#include "util.h"
#include "config.h"
+enum { MIN_GIF_DELAY = 50 };
+
int zl_cnt;
float zoom_min;
float zoom_max;
@@ -44,6 +46,7 @@ void img_init(img_t *img, win_t *win) {
if (img) {
img->im = NULL;
img->multi.cap = img->multi.cnt = 0;
+ img->multi.animate = 0;
img->zoom = options->zoom;
img->zoom = MAX(img->zoom, zoom_min);
img->zoom = MIN(img->zoom, zoom_max);
@@ -72,11 +75,12 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
int intoffset[] = { 0, 4, 2, 1 };
int intjump[] = { 8, 8, 4, 2 };
int err = 0, transp = -1;
+ unsigned int delay = 0;
if (img->multi.cap == 0) {
img->multi.cap = 8;
- img->multi.frames = (Imlib_Image**)
- s_malloc(sizeof(Imlib_Image*) * img->multi.cap);
+ img->multi.frames = (img_frame_t*)
+ s_malloc(sizeof(img_frame_t) * img->multi.cap);
}
img->multi.cnt = 0;
img->multi.sel = 0;
@@ -107,6 +111,10 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
transp = (int) ext[4];
else
transp = -1;
+
+ delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]);
+ if (delay)
+ delay = MAX(delay, MIN_GIF_DELAY);
}
ext = NULL;
DGifGetExtensionNext(gif, &ext);
@@ -186,11 +194,13 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
if (img->multi.cnt == img->multi.cap) {
img->multi.cap *= 2;
- img->multi.frames = (Imlib_Image**)
+ img->multi.frames = (img_frame_t*)
s_realloc(img->multi.frames,
- img->multi.cap * sizeof(Imlib_Image*));
+ img->multi.cap * sizeof(img_frame_t));
}
- img->multi.frames[img->multi.cnt++] = im;
+ img->multi.frames[img->multi.cnt].im = im;
+ img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY;
+ img->multi.cnt++;
}
} while (rec != TERMINATE_RECORD_TYPE);
@@ -199,13 +209,15 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
if (!err && img->multi.cnt > 1) {
imlib_context_set_image(img->im);
imlib_free_image();
- img->im = img->multi.frames[0];
+ img->im = img->multi.frames[0].im;
+ img->multi.animate = GIF_AUTOPLAY;
} else {
for (i = 0; i < img->multi.cnt; i++) {
- imlib_context_set_image(img->multi.frames[i]);
+ imlib_context_set_image(img->multi.frames[i].im);
imlib_free_image();
}
img->multi.cnt = 0;
+ img->multi.animate = 0;
}
imlib_context_set_image(img->im);
@@ -256,7 +268,7 @@ void img_close(img_t *img, int decache) {
if (img->multi.cnt) {
for (i = 0; i < img->multi.cnt; i++) {
- imlib_context_set_image(img->multi.frames[i]);
+ imlib_context_set_image(img->multi.frames[i].im);
imlib_free_image();
}
img->multi.cnt = 0;
@@ -378,27 +390,6 @@ void img_render(img_t *img, win_t *win) {
win_draw(win);
}
-int img_change_frame(img_t *img, int d) {
- if (!img || !img->multi.cnt || !d)
- return 0;
-
- d += img->multi.sel;
- if (d < 0)
- d = 0;
- else if (d >= img->multi.cnt)
- d = img->multi.cnt - 1;
-
- img->multi.sel = d;
- img->im = img->multi.frames[d];
-
- imlib_context_set_image(img->im);
- img->w = imlib_image_get_width();
- img->h = imlib_image_get_height();
- img->checkpan = 1;
-
- return 1;
-}
-
int img_fit_win(img_t *img, win_t *win) {
if (!img || !img->im || !win)
return 0;
@@ -569,3 +560,58 @@ void img_toggle_antialias(img_t *img) {
imlib_context_set_anti_alias(img->aa);
}
}
+
+int img_frame_goto(img_t *img, int n) {
+ if (!img || n < 0 || n >= img->multi.cnt)
+ return 0;
+
+ if (n == img->multi.sel)
+ return 0;
+
+ img->multi.sel = n;
+ img->im = img->multi.frames[n].im;
+
+ imlib_context_set_image(img->im);
+ img->w = imlib_image_get_width();
+ img->h = imlib_image_get_height();
+ img->checkpan = 1;
+
+ return 1;
+}
+
+int img_frame_navigate(img_t *img, int d) {
+ if (!img || !img->multi.cnt || !d)
+ return 0;
+
+ d += img->multi.sel;
+ if (d < 0)
+ d = 0;
+ else if (d >= img->multi.cnt)
+ d = img->multi.cnt - 1;
+
+ return img_frame_goto(img, d);
+}
+
+int img_frame_animate(img_t *img, int restart) {
+ if (!img || !img->multi.cnt)
+ return 0;
+
+ if (!img->multi.animate && !restart)
+ return 0;
+
+ if (restart) {
+ img_frame_goto(img, 0);
+ img->multi.animate = 1;
+ } else if (img->multi.sel + 1 >= img->multi.cnt) {
+ if (!GIF_LOOP) {
+ img->multi.animate = 0;
+ return 0;
+ } else {
+ img_frame_goto(img, 0);
+ }
+ } else {
+ img_frame_goto(img, img->multi.sel + 1);
+ }
+
+ return img->multi.frames[img->multi.sel].delay;
+}
diff --git a/image.h b/image.h
index 408992e..cf50718 100644
--- a/image.h
+++ b/image.h
@@ -25,10 +25,16 @@
#include "window.h"
typedef struct {
+ Imlib_Image *im;
+ unsigned int delay;
+} img_frame_t;
+
+typedef struct {
+ img_frame_t *frames;
int cap;
int cnt;
int sel;
- Imlib_Image **frames;
+ unsigned char animate;
} multi_img_t;
typedef struct {
@@ -56,8 +62,6 @@ void img_close(img_t*, int);
void img_render(img_t*, win_t*);
-int img_change_frame(img_t*, int);
-
int img_fit_win(img_t*, win_t*);
int img_center(img_t*, win_t*);
@@ -74,4 +78,7 @@ void img_rotate_right(img_t*, win_t*);
void img_toggle_antialias(img_t*);
+int img_frame_navigate(img_t*, int);
+int img_frame_animate(img_t*, int);
+
#endif /* IMAGE_H */
diff --git a/main.c b/main.c
index 27788db..3e2f353 100644
--- a/main.c
+++ b/main.c
@@ -54,6 +54,7 @@ char win_title[TITLE_LEN];
int timo_cursor;
int timo_redraw;
+int timo_adelay; /* multi-frame animation delay time */
void cleanup() {
static int in = 0;
@@ -140,6 +141,9 @@ void load_image(int new) {
filesize = fstats.st_size;
else
filesize = 0;
+
+ if (img.multi.cnt && img.multi.animate)
+ timo_adelay = img.multi.frames[img.multi.sel].delay;
}
void update_title() {
@@ -296,10 +300,12 @@ void run() {
} else {
timo_redraw = TO_THUMBS_LOAD;
}
- } else if (timo_cursor || timo_redraw) {
+ }
+
+ if (timo_cursor || timo_redraw || timo_adelay) {
/* check active timeouts */
gettimeofday(&t0, 0);
- timeout = MIN(timo_cursor + 1, timo_redraw + 1);
+ timeout = min_int_nz(3, timo_cursor, timo_redraw, timo_adelay);
MSEC_TO_TIMEVAL(timeout, &tt);
xfd = ConnectionNumber(win.env.dpy);
FD_ZERO(&fds);
@@ -321,7 +327,15 @@ void run() {
if (!timo_redraw)
redraw();
}
- if ((timo_cursor || timo_redraw) && !XPending(win.env.dpy))
+ if (timo_adelay) {
+ timo_adelay = MAX(0, timo_adelay - timeout);
+ if (!timo_adelay) {
+ if ((timo_adelay = img_frame_animate(&img, 0)))
+ redraw();
+ }
+ }
+ if ((timo_cursor || timo_redraw || timo_adelay) &&
+ !XPending(win.env.dpy))
continue;
}
diff --git a/util.c b/util.c
index 0c4574e..5bed511 100644
--- a/util.c
+++ b/util.c
@@ -87,6 +87,19 @@ void die(const char* fmt, ...) {
exit(1);
}
+int min_int_nz(int n, ...) {
+ va_list args;
+ int i, a, m = 0;
+
+ va_start(args, n);
+ for (i = 0; i < n; i++) {
+ if ((a = va_arg(args, int)) && (!m || a < m))
+ m = a;
+ }
+ va_end(args);
+ return m;
+}
+
void size_readable(float *size, const char **unit) {
const char *units[] = { "", "K", "M", "G" };
int i;
diff --git a/util.h b/util.h
index e0d28c0..a891054 100644
--- a/util.h
+++ b/util.h
@@ -60,6 +60,8 @@ char* s_strdup(char*);
void warn(const char*, ...);
void die(const char*, ...);
+int min_int_nz(int, ...);
+
void size_readable(float*, const char**);
char* absolute_path(const char*);