Krolyxon
Commit 87a9828

Branches

Refs →

nsxivimage.c

364 lines · 7.5 KB · C

1/* sxiv: image.c
2 * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#include <unistd.h>
20
21#include "config.h"
22#include "icon.h"
23#include "image.h"
24#include "options.h"
25#include "util.h"
26
27int zl_cnt;
28float zoom_min;
29float zoom_max;
30
31Imlib_Image *im_broken;
32
33void img_init(img_t *img, win_t *win) {
34 zl_cnt = sizeof(zoom_levels) / sizeof(zoom_levels[0]);
35 zoom_min = zoom_levels[0] / 100.0;
36 zoom_max = zoom_levels[zl_cnt - 1] / 100.0;
37
38 im_broken = imlib_create_image_using_data(32, 32, icon_broken);
39
40 if (img) {
41 img->im = NULL;
42 img->zoom = options->zoom;
43 img->zoom = MAX(img->zoom, zoom_min);
44 img->zoom = MIN(img->zoom, zoom_max);
45 img->aa = options->aa;
46 img->alpha = 1;
47 }
48
49 if (win) {
50 imlib_context_set_display(win->env.dpy);
51 imlib_context_set_visual(win->env.vis);
52 imlib_context_set_colormap(win->env.cmap);
53 }
54}
55
56void img_free(img_t* img) {
57 imlib_context_set_image(im_broken);
58 imlib_free_image();
59}
60
61int img_check(const char *filename) {
62 Imlib_Image *im;
63
64 if (!filename)
65 return 0;
66
67 if (!access(filename, F_OK) && (im = imlib_load_image(filename))) {
68 imlib_context_set_image(im);
69 imlib_image_set_changes_on_disk();
70 imlib_free_image();
71 return 1;
72 } else {
73 warn("could not open file: %s", filename);
74 return 0;
75 }
76}
77
78int img_load(img_t *img, const char *filename) {
79 if (!img || !filename)
80 return 0;
81
82 if (!access(filename, F_OK) && (img->im = imlib_load_image(filename))) {
83 imlib_context_set_image(img->im);
84 imlib_image_set_changes_on_disk();
85 imlib_context_set_anti_alias(img->aa);
86 img->scalemode = options->scalemode;
87 } else {
88 warn("could not open file: %s", filename);
89 imlib_context_set_image(im_broken);
90 imlib_context_set_anti_alias(0);
91 img->scalemode = SCALE_DOWN;
92 }
93
94 img->re = 0;
95 img->checkpan = 0;
96
97 img->w = imlib_image_get_width();
98 img->h = imlib_image_get_height();
99
100 return 1;
101}
102
103void img_close(img_t *img, int decache) {
104 if (img && img->im) {
105 imlib_context_set_image(img->im);
106 if (decache)
107 imlib_free_image_and_decache();
108 else
109 imlib_free_image();
110 img->im = NULL;
111 }
112}
113
114void img_check_pan(img_t *img, win_t *win) {
115 if (!img || !win)
116 return;
117
118 if (img->w * img->zoom > win->w) {
119 if (img->x > 0 && img->x + img->w * img->zoom > win->w)
120 img->x = 0;
121 if (img->x < 0 && img->x + img->w * img->zoom < win->w)
122 img->x = win->w - img->w * img->zoom;
123 } else {
124 img->x = (win->w - img->w * img->zoom) / 2;
125 }
126 if (img->h * img->zoom > win->h) {
127 if (img->y > 0 && img->y + img->h * img->zoom > win->h)
128 img->y = 0;
129 if (img->y < 0 && img->y + img->h * img->zoom < win->h)
130 img->y = win->h - img->h * img->zoom;
131 } else {
132 img->y = (win->h - img->h * img->zoom) / 2;
133 }
134}
135
136int img_fit(img_t *img, win_t *win) {
137 float oz, zw, zh;
138
139 if (!img || !win)
140 return 0;
141
142 oz = img->zoom;
143 zw = (float) win->w / (float) img->w;
144 zh = (float) win->h / (float) img->h;
145
146 img->zoom = MIN(zw, zh);
147 img->zoom = MAX(img->zoom, zoom_min);
148 img->zoom = MIN(img->zoom, zoom_max);
149
150 return oz != img->zoom;
151}
152
153void img_render(img_t *img, win_t *win) {
154 int sx, sy, sw, sh;
155 int dx, dy, dw, dh;
156
157 if (!img || !win)
158 return;
159
160 if (img->scalemode != SCALE_ZOOM) {
161 img_fit(img, win);
162 if (img->scalemode == SCALE_DOWN && img->zoom > 1.0)
163 img->zoom = 1.0;
164 }
165
166 if (!img->re) {
167 /* rendered for the first time */
168 img->re = 1;
169 if (img->zoom * img->w <= win->w)
170 img->x = (win->w - img->w * img->zoom) / 2;
171 else
172 img->x = 0;
173 if (img->zoom * img->h <= win->h)
174 img->y = (win->h - img->h * img->zoom) / 2;
175 else
176 img->y = 0;
177 }
178
179 if (img->checkpan) {
180 img_check_pan(img, win);
181 img->checkpan = 0;
182 }
183
184 /* calculate source and destination offsets */
185 if (img->x < 0) {
186 sx = -img->x / img->zoom;
187 sw = win->w / img->zoom;
188 dx = 0;
189 dw = win->w;
190 } else {
191 sx = 0;
192 sw = img->w;
193 dx = img->x;
194 dw = img->w * img->zoom;
195 }
196 if (img->y < 0) {
197 sy = -img->y / img->zoom;
198 sh = win->h / img->zoom;
199 dy = 0;
200 dh = win->h;
201 } else {
202 sy = 0;
203 sh = img->h;
204 dy = img->y;
205 dh = img->h * img->zoom;
206 }
207
208 win_clear(win);
209
210 if (img->im)
211 imlib_context_set_image(img->im);
212 else
213 imlib_context_set_image(im_broken);
214
215 if (imlib_image_has_alpha() && !img->alpha)
216 win_draw_rect(win, win->pm, dx, dy, dw, dh, True, 0, win->white);
217
218 imlib_context_set_drawable(win->pm);
219 imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw, dh);
220
221 win_draw(win);
222}
223
224int img_fit_win(img_t *img, win_t *win) {
225 if (!img || !img->im || !win)
226 return 0;
227
228 img->scalemode = SCALE_FIT;
229 return img_fit(img, win);
230}
231
232int img_center(img_t *img, win_t *win) {
233 int ox, oy;
234
235 if (!img || !win)
236 return 0;
237
238 ox = img->x;
239 oy = img->y;
240
241 img->x = (win->w - img->w * img->zoom) / 2;
242 img->y = (win->h - img->h * img->zoom) / 2;
243
244 return ox != img->x || oy != img->y;
245}
246
247int img_zoom(img_t *img, float z) {
248 if (!img || !img->im)
249 return 0;
250
251 z = MAX(z, zoom_min);
252 z = MIN(z, zoom_max);
253
254 img->scalemode = SCALE_ZOOM;
255
256 if (z != img->zoom) {
257 img->x -= (img->w * z - img->w * img->zoom) / 2;
258 img->y -= (img->h * z - img->h * img->zoom) / 2;
259 img->zoom = z;
260 img->checkpan = 1;
261 return 1;
262 } else {
263 return 0;
264 }
265}
266
267int img_zoom_in(img_t *img) {
268 int i;
269
270 if (!img || !img->im)
271 return 0;
272
273 for (i = 1; i < zl_cnt; ++i) {
274 if (zoom_levels[i] > img->zoom * 100.0)
275 return img_zoom(img, zoom_levels[i] / 100.0);
276 }
277 return 0;
278}
279
280int img_zoom_out(img_t *img) {
281 int i;
282
283 if (!img || !img->im)
284 return 0;
285
286 for (i = zl_cnt - 2; i >= 0; --i) {
287 if (zoom_levels[i] < img->zoom * 100.0)
288 return img_zoom(img, zoom_levels[i] / 100.0);
289 }
290 return 0;
291}
292
293int img_move(img_t *img, win_t *win, int dx, int dy) {
294 int ox, oy;
295
296 if (!img || !img->im || !win)
297 return 0;
298
299 ox = img->x;
300 oy = img->y;
301
302 img->x += dx;
303 img->y += dy;
304
305 img_check_pan(img, win);
306
307 return ox != img->x || oy != img->y;
308}
309
310int img_pan(img_t *img, win_t *win, pandir_t dir) {
311 if (!img || !img->im || !win)
312 return 0;
313
314 switch (dir) {
315 case PAN_LEFT:
316 return img_move(img, win, win->w / 5, 0);
317 case PAN_RIGHT:
318 return img_move(img, win, win->w / 5 * -1, 0);
319 case PAN_UP:
320 return img_move(img, win, 0, win->h / 5);
321 case PAN_DOWN:
322 return img_move(img, win, 0, win->h / 5 * -1);
323 }
324
325 return 0;
326}
327
328void img_rotate(img_t *img, win_t *win, int d) {
329 int ox, oy, tmp;
330
331 if (!img || !img->im || !win)
332 return;
333
334 ox = d == 1 ? img->x : win->w - img->x - img->w * img->zoom;
335 oy = d == 3 ? img->y : win->h - img->y - img->h * img->zoom;
336
337 imlib_context_set_image(img->im);
338 imlib_image_orientate(d);
339
340 img->x = oy + (win->w - win->h) / 2;
341 img->y = ox + (win->h - win->w) / 2;
342
343 tmp = img->w;
344 img->w = img->h;
345 img->h = tmp;
346
347 img->checkpan = 1;
348}
349
350void img_rotate_left(img_t *img, win_t *win) {
351 img_rotate(img, win, 3);
352}
353
354void img_rotate_right(img_t *img, win_t *win) {
355 img_rotate(img, win, 1);
356}
357
358void img_toggle_antialias(img_t *img) {
359 if (img && img->im) {
360 img->aa ^= 1;
361 imlib_context_set_image(img->im);
362 imlib_context_set_anti_alias(img->aa);
363 }
364}