Krolyxon
Commit 5cb6d12

Branches

Refs →

nsxivimage.c

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