From 79c7e6178e9b577158408157ec23a477556ecf16 Mon Sep 17 00:00:00 2001
From: Bert <ber.t@gmx.com>
Date: Tue, 18 Jan 2011 20:11:28 +0100
Subject: [PATCH] Render image on window

---
 app.c    |  4 +++-
 image.c  | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 image.h  |  4 ++--
 sxiv.h   |  5 ++++-
 window.c |  7 +++++++
 window.h |  1 +
 6 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/app.c b/app.c
index 2a3e0c2..3c1f88a 100644
--- a/app.c
+++ b/app.c
@@ -28,7 +28,7 @@ void app_init(app_t *app) {
 
 	app->fileidx = 0;
 
-	app->img.zoom = 100;
+	app->img.zoom = 1.0;
 	app->img.scalemode = SCALE_MODE;
 
 	app->win.w = WIN_WIDTH;
@@ -52,4 +52,6 @@ void app_load_image(app_t *app) {
 		return;
 
 	img_load(&app->img, app->filenames[app->fileidx]);
+
+	img_render(&app->img, &app->win);
 }
diff --git a/image.c b/image.c
index a430b81..235b2d4 100644
--- a/image.c
+++ b/image.c
@@ -25,7 +25,7 @@
 void imlib_init(win_t *win) {
 	if (!win)
 		return;
-	
+
 	imlib_context_set_display(win->env.dpy);
 	imlib_context_set_visual(win->env.vis);
 	imlib_context_set_colormap(win->env.cmap);
@@ -41,9 +41,64 @@ void img_load(img_t *img, char *filename) {
 
 	if (!(img->im = imlib_load_image(filename)))
 		DIE("could not open image: %s", filename);
-	
+
 	imlib_context_set_image(img->im);
-	
+
 	img->w = imlib_image_get_width();
 	img->h = imlib_image_get_height();
 }
+
+void img_render(img_t *img, win_t *win) {
+	float zw, zh;
+	unsigned int sx, sy, sw, sh;
+	unsigned int dx, dy, dw, dh;
+
+	if (!img || !win)
+		return;
+
+	/* set zoom level to fit image into window */
+	if (img->scalemode != SCALE_ZOOM) {
+		zw = (float) win->w / (float) img->w;
+		zh = (float) win->h / (float) img->h;
+		img->zoom = MIN(zw, zh);
+
+		if (img->zoom * 100.0 < ZOOM_MIN)
+			img->zoom = ZOOM_MIN / 100.0;
+		else if (img->zoom * 100.0 > ZOOM_MAX)
+			img->zoom = ZOOM_MAX / 100.0;
+
+		if (img->scalemode == SCALE_DOWN && img->zoom > 1.0)
+			img->zoom = 1.0;
+	}
+
+	/* center image in window */
+	img->x = (win->w - img->w * img->zoom) / 2;
+	img->y = (win->h - img->h * img->zoom) / 2;
+
+	if (img->x < 0) {
+		sx = -img->x / img->zoom;
+		sw = (img->x + win->w) / img->zoom;
+		dx = 0;
+		dw = win->w;
+	} else {
+		sx = 0;
+		sw = img->w;
+		dx = img->x;
+		dw = img->w * img->zoom;
+	}
+	if (img->y < 0) {
+		sy = -img->y / img->zoom;
+		sh = (img->y + win->h) / img->zoom;
+		dy = 0;
+		dh = win->h;
+	} else {
+		sy = 0;
+		sh = img->h;
+		dy = img->y;
+		dh = img->h * img->zoom;
+	}
+
+	win_clear(win);
+
+	imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw, dh);
+}
diff --git a/image.h b/image.h
index 78d4126..7eaf197 100644
--- a/image.h
+++ b/image.h
@@ -30,7 +30,7 @@ typedef enum scalemode_e {
 } scalemode_t;
 
 typedef struct img_s {
-	int zoom;
+	float zoom;
 	scalemode_t scalemode;
 	int w;
 	int h;
@@ -43,6 +43,6 @@ typedef struct img_s {
 void imlib_init(win_t*);
 
 void img_load(img_t*, char*);
-void img_display(img_t*, win_t*);
+void img_render(img_t*, win_t*);
 
 #endif /* IMAGE_H */
diff --git a/sxiv.h b/sxiv.h
index 1ebcf57..97252af 100644
--- a/sxiv.h
+++ b/sxiv.h
@@ -23,6 +23,9 @@
 
 #define VERSION "git-20110117"
 
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
 #define WARN(...)                                                  \
 	do {                                                             \
 	  fprintf(stderr, "sxiv: %s:%d: warning: ", __FILE__, __LINE__); \
@@ -30,7 +33,7 @@
 		fprintf(stderr, "\n");                                         \
 	} while (0)
 
-#define DIE(...)                                                 \
+#define DIE(...)                                                   \
   do {                                                             \
 		fprintf(stderr, "sxiv: %s:%d: error: ", __FILE__, __LINE__);   \
 		fprintf(stderr, __VA_ARGS__);                                  \
diff --git a/window.c b/window.c
index f8afad6..223e4c6 100644
--- a/window.c
+++ b/window.c
@@ -106,3 +106,10 @@ int win_configure(win_t *win, XConfigureEvent *cev) {
 	win->bw = cev->border_width;
 	return changed;
 }
+
+void win_clear(win_t *win) {
+	if (!win)
+		return;
+
+	XClearWindow(win->env.dpy, win->xwin);
+}
diff --git a/window.h b/window.h
index 3a080f0..3a1b230 100644
--- a/window.h
+++ b/window.h
@@ -47,5 +47,6 @@ void win_open(win_t*);
 void win_close(win_t*);
 
 int win_configure(win_t*, XConfigureEvent*);
+void win_clear(win_t*);
 
 #endif /* WINDOW_H */