Allow ~/... and $HOME/... paths for more stuff.
[monky] / src / imlib2.c
1 /* Conky, a system monitor, based on torsmo
2  *
3  * Please see COPYING for details
4  *
5  * Copyright (c) 2005-2009 Brenden Matthews, et. al.
6  * All rights reserved.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #include "imlib2.h"
23 #include "config.h"
24 #include "logging.h"
25 #include "common.h"
26
27 #include <Imlib2.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <limits.h>
32
33 struct image_list_s {
34         char name[DEFAULT_TEXT_BUFFER_SIZE];
35         Imlib_Image image;
36         int x, y, w, h;
37         int wh_set;
38         struct image_list_s *next;
39 };
40
41 struct image_list_s *image_list_start, *image_list_end;
42
43 /* areas to update */
44 Imlib_Updates updates, current_update;
45 /* our virtual framebuffer image we draw into */
46 Imlib_Image buffer, image;
47
48 static int cache_size_set = 0;
49
50 #define DEFAULT_CACHE_SIZE 4096 * 1024 /* default cache size for loaded images */
51
52 void cimlib_set_cache_size(long size)
53 {
54         imlib_set_cache_size(size);
55         cache_size_set = 1;
56 }
57
58 void cimlib_cleanup(void)
59 {
60         struct image_list_s *cur = image_list_start, *last = NULL;
61         while (cur) {
62                 last = cur;
63                 cur = last->next;
64                 free(last);
65         }
66         image_list_start = image_list_end = NULL;
67 }
68
69 void cimlib_init(Display *display, Window drawable, Visual *visual, Colormap colourmap)
70 {
71         image_list_start = image_list_end = NULL;
72         if (!cache_size_set) cimlib_set_cache_size(DEFAULT_CACHE_SIZE);
73         /* set the maximum number of colors to allocate for 8bpp and less to 256 */
74         imlib_set_color_usage(256);
75         /* dither for depths < 24bpp */
76         imlib_context_set_dither(1);
77         /* set the display , visual, colormap and drawable we are using */
78         imlib_context_set_display(display);
79         imlib_context_set_visual(visual);
80         imlib_context_set_colormap(colourmap);
81         imlib_context_set_drawable(drawable);
82 }
83
84 void cimlib_add_image(const char *args)
85 {
86         struct image_list_s *cur = NULL;
87         char *tmp;
88
89         cur = malloc(sizeof(struct image_list_s));
90         memset(cur, 0, sizeof(struct image_list_s));
91
92         if (!sscanf(args, "%1024s", cur->name)) {
93                 ERR("Invalid args for $image.  Format is: '<path to image> (-p x,y) (-s WxH)' (got '%s')", args);
94         }
95         to_real_path(cur->name, cur->name);
96         // now we check for optional args
97         tmp = strstr(args, "-p ");
98         if (tmp) {
99                 tmp += 3;
100                 sscanf(tmp, "%i,%i", &cur->x, &cur->y);
101         }
102         tmp = strstr(args, "-s ");
103         if (tmp) {
104                 tmp += 3;
105                 if (sscanf(tmp, "%ix%i", &cur->w, &cur->h)) {
106                         cur->wh_set = 1;
107                 }
108         }
109
110         if (image_list_end) {
111                 image_list_end->next = cur;
112                 image_list_end = cur;
113         } else {
114                 image_list_start = image_list_end = cur;
115         }
116 }
117
118 static void cimlib_draw_image(struct image_list_s *cur, int *clip_x, int *clip_y, int *clip_x2, int *clip_y2)
119 {
120         image = imlib_load_image(cur->name);
121         if (image) {
122                 int w, h;
123                 DBGP("Drawing image '%s' at (%i,%i) scaled to %ix%i", cur->name, cur->x, cur->y, cur->w, cur->h);
124                 imlib_context_set_image(image);
125                 /* turn alpha channel on */
126                 imlib_image_set_has_alpha(1);
127                 w = imlib_image_get_width();
128                 h = imlib_image_get_height();
129                 if (!cur->wh_set) {
130                         cur->w = w;
131                         cur->h = h;
132                 }
133                 imlib_context_set_image(buffer);
134                 imlib_blend_image_onto_image(image, 1, 0, 0, w, h,
135                                 cur->x, cur->y, cur->w, cur->h);
136                 imlib_context_set_image(image);
137                 imlib_free_image();
138                 if (cur->x < *clip_x) *clip_x = cur->x;
139                 if (cur->y < *clip_y) *clip_y = cur->y;
140                 if (cur->x + cur->w > *clip_x2) *clip_x2 = cur->x + cur->w;
141                 if (cur->y + cur->h > *clip_y2) *clip_y2 = cur->y + cur->h;
142         } else {
143                 ERR("Unable to load image '%s'", cur->name);
144         }
145 }
146
147 static void cimlib_draw_all(int *clip_x, int *clip_y, int *clip_x2, int *clip_y2)
148 {
149         struct image_list_s *cur = image_list_start;
150         while (cur) {
151                 cimlib_draw_image(cur, clip_x, clip_y, clip_x2, clip_y2);
152                 cur = cur->next;
153         }
154 }
155
156 void cimlib_render(int x, int y, int width, int height)
157 {
158         int clip_x = INT_MAX, clip_y = INT_MAX;
159         int clip_x2 = 0, clip_y2 = 0;
160
161         if (!image_list_start) return; /* are we actually drawing anything? */
162         /* take all the little rectangles to redraw and merge them into
163          * something sane for rendering */
164         buffer = imlib_create_image(width, height);
165         /* clear our buffer */
166         imlib_context_set_image(buffer);
167         imlib_image_clear();
168         /* we can blend stuff now */
169         imlib_context_set_blend(1);
170         /* turn alpha channel on */
171         imlib_image_set_has_alpha(1);
172
173         cimlib_draw_all(&clip_x, &clip_y, &clip_x2, &clip_y2);
174
175         /* set the buffer image as our current image */
176         imlib_context_set_image(buffer);
177
178         /* setup our clip rect */
179         if (clip_x == INT_MAX) clip_x = 0;
180         if (clip_y == INT_MAX) clip_y = 0;
181
182         /* render the image at 0, 0 */
183         imlib_render_image_part_on_drawable_at_size(clip_x, clip_y, clip_x2 - clip_x,
184                         clip_y2 - clip_y, x + clip_x, y + clip_y, clip_x2 - clip_x,
185                         clip_y2 - clip_y);
186         /* don't need that temporary buffer image anymore */
187         imlib_free_image();
188 }
189