Add awesome.load_image()
[awesome.git] / draw.c
bloba2dd5111ff058884433f6aab27861862f0ea7fa9
1 /*
2 * draw.c - draw functions
4 * Copyright © 2007-2009 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <cairo-xcb.h>
24 #include "config.h"
26 #include <langinfo.h>
27 #include <iconv.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <math.h>
32 #include <Imlib2.h>
34 #include "globalconf.h"
35 #include "screen.h"
37 #include "common/xutil.h"
39 /** Convert text from any charset to UTF-8 using iconv.
40 * \param iso The ISO string to convert.
41 * \param len The string size.
42 * \param dest The destination pointer. Memory will be allocated, up to you to
43 * free, like any char *.
44 * \param dlen The destination length, can be NULL.
45 * \return True if conversion was done.
47 bool
48 draw_iso2utf8(const char *iso, size_t len, char **dest, ssize_t *dlen)
50 static iconv_t iso2utf8 = (iconv_t) -1;
51 static int8_t dont_need_convert = -1;
53 if(dont_need_convert == -1)
54 dont_need_convert = A_STREQ(nl_langinfo(CODESET), "UTF-8");
56 if(!len || dont_need_convert)
57 return false;
59 if(iso2utf8 == (iconv_t) -1)
61 iso2utf8 = iconv_open("UTF-8", nl_langinfo(CODESET));
62 if(iso2utf8 == (iconv_t) -1)
64 if(errno == EINVAL)
65 warn("unable to convert text from %s to UTF-8, not available",
66 nl_langinfo(CODESET));
67 else
68 warn("unable to convert text: %s", strerror(errno));
70 return false;
74 size_t orig_utf8len, utf8len;
75 char *utf8;
77 orig_utf8len = utf8len = 2 * len + 1;
78 utf8 = *dest = p_new(char, utf8len);
80 if(iconv(iso2utf8, (char **) &iso, &len, &utf8, &utf8len) == (size_t) -1)
82 warn("text conversion failed: %s", strerror(errno));
83 p_delete(dest);
84 return false;
87 if(dlen)
88 *dlen = orig_utf8len - utf8len;
90 return true;
93 static cairo_user_data_key_t data_key;
95 static inline void
96 free_data(void *data)
98 p_delete(&data);
101 /** Create a surface object on the lua stack from this image data.
102 * \param L The lua stack.
103 * \param width The width of the image.
104 * \param height The height of the image
105 * \param data The image's data in ARGB format, will be copied by this function.
106 * \return Number of items pushed on the lua stack.
109 luaA_surface_from_data(lua_State *L, int width, int height, uint32_t *data)
111 unsigned long int len = width * height;
112 unsigned long int i;
113 uint32_t *buffer = p_new(uint32_t, len);
114 cairo_surface_t *surface;
116 /* Cairo wants premultiplied alpha, meh :( */
117 for(i = 0; i < len; i++)
119 uint8_t a = (data[i] >> 24) & 0xff;
120 double alpha = a / 255.0;
121 uint8_t r = ((data[i] >> 16) & 0xff) * alpha;
122 uint8_t g = ((data[i] >> 8) & 0xff) * alpha;
123 uint8_t b = ((data[i] >> 0) & 0xff) * alpha;
124 buffer[i] = (a << 24) | (r << 16) | (g << 8) | b;
127 surface =
128 cairo_image_surface_create_for_data((unsigned char *) buffer,
129 CAIRO_FORMAT_ARGB32,
130 width,
131 height,
132 width*4);
133 /* This makes sure that buffer will be freed */
134 cairo_surface_set_user_data(surface, &data_key, buffer, &free_data);
136 /* This will increase the reference count of the surface */
137 int ret = oocairo_surface_push(globalconf.L, surface);
138 /* So we have to drop our own reference */
139 cairo_surface_destroy(surface);
141 return ret;
144 /** Duplicate the specified image surface.
145 * \param surface The surface to copy
146 * \return A pointer to a new cairo image surface.
148 cairo_surface_t *
149 draw_dup_image_surface(cairo_surface_t *surface)
151 cairo_surface_t *res = cairo_image_surface_create(
152 cairo_image_surface_get_format(surface),
153 cairo_image_surface_get_width(surface),
154 cairo_image_surface_get_height(surface));
156 cairo_t *cr = cairo_create(res);
157 cairo_set_source_surface(cr, surface, 0, 0);
158 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
159 cairo_paint(cr);
160 cairo_destroy(cr);
162 return res;
165 static const char *
166 image_imlib_load_strerror(Imlib_Load_Error e)
168 switch(e)
170 case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST:
171 return "no such file or directory";
172 case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY:
173 return "file is a directory";
174 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ:
175 return "read permission denied";
176 case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT:
177 return "no loader for file format";
178 case IMLIB_LOAD_ERROR_PATH_TOO_LONG:
179 return "path too long";
180 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT:
181 return "path component non existent";
182 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY:
183 return "path component not a directory";
184 case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE:
185 return "path points outside address space";
186 case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS:
187 return "too many symbolic links";
188 case IMLIB_LOAD_ERROR_OUT_OF_MEMORY:
189 return "out of memory";
190 case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS:
191 return "out of file descriptors";
192 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE:
193 return "write permission denied";
194 case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE:
195 return "out of disk space";
196 case IMLIB_LOAD_ERROR_UNKNOWN:
197 return "unknown error, that's really bad";
198 case IMLIB_LOAD_ERROR_NONE:
199 return "no error, oops";
202 return "unknown error";
205 /** Load the specified path into a cairo surface
206 * \param L Lua state
207 * \param path file to load
208 * \return A cairo image surface or NULL on error.
211 draw_load_image(lua_State *L, const char *path)
213 Imlib_Image imimage;
214 Imlib_Load_Error e = IMLIB_LOAD_ERROR_NONE;
215 int ret;
217 imimage = imlib_load_image_with_error_return(path, &e);
218 if (!imimage) {
219 luaL_error(L, "Cannot load image '%s': %s", path, image_imlib_load_strerror(e));
220 return 0;
223 imlib_context_set_image(imimage);
224 ret = luaA_surface_from_data(L, imlib_image_get_width(),
225 imlib_image_get_height(), imlib_image_get_data_for_reading_only());
226 imlib_free_image_and_decache();
227 return ret;
230 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80