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>
34 #include "globalconf.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.
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
)
59 if(iso2utf8
== (iconv_t
) -1)
61 iso2utf8
= iconv_open("UTF-8", nl_langinfo(CODESET
));
62 if(iso2utf8
== (iconv_t
) -1)
65 warn("unable to convert text from %s to UTF-8, not available",
66 nl_langinfo(CODESET
));
68 warn("unable to convert text: %s", strerror(errno
));
74 size_t orig_utf8len
, utf8len
;
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
));
88 *dlen
= orig_utf8len
- utf8len
;
93 static cairo_user_data_key_t data_key
;
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 draw_surface_from_data(int width
, int height
, uint32_t *data
)
111 unsigned long int len
= width
* height
;
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
;
128 cairo_image_surface_create_for_data((unsigned char *) buffer
,
133 /* This makes sure that buffer will be freed */
134 cairo_surface_set_user_data(surface
, &data_key
, buffer
, &free_data
);
139 /** Duplicate the specified image surface.
140 * \param surface The surface to copy
141 * \return A pointer to a new cairo image surface.
144 draw_dup_image_surface(cairo_surface_t
*surface
)
146 cairo_surface_t
*res
= cairo_image_surface_create(
147 cairo_image_surface_get_format(surface
),
148 cairo_image_surface_get_width(surface
),
149 cairo_image_surface_get_height(surface
));
151 cairo_t
*cr
= cairo_create(res
);
152 cairo_set_source_surface(cr
, surface
, 0, 0);
153 cairo_set_operator(cr
, CAIRO_OPERATOR_SOURCE
);
161 image_imlib_load_strerror(Imlib_Load_Error e
)
165 case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST
:
166 return "no such file or directory";
167 case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY
:
168 return "file is a directory";
169 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ
:
170 return "read permission denied";
171 case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT
:
172 return "no loader for file format";
173 case IMLIB_LOAD_ERROR_PATH_TOO_LONG
:
174 return "path too long";
175 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT
:
176 return "path component non existent";
177 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY
:
178 return "path component not a directory";
179 case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE
:
180 return "path points outside address space";
181 case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS
:
182 return "too many symbolic links";
183 case IMLIB_LOAD_ERROR_OUT_OF_MEMORY
:
184 return "out of memory";
185 case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS
:
186 return "out of file descriptors";
187 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE
:
188 return "write permission denied";
189 case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE
:
190 return "out of disk space";
191 case IMLIB_LOAD_ERROR_UNKNOWN
:
192 return "unknown error, that's really bad";
193 case IMLIB_LOAD_ERROR_NONE
:
194 return "no error, oops";
197 return "unknown error";
200 /** Load the specified path into a cairo surface
202 * \param path file to load
203 * \return A cairo image surface or NULL on error.
206 draw_load_image(lua_State
*L
, const char *path
)
209 Imlib_Load_Error e
= IMLIB_LOAD_ERROR_NONE
;
210 cairo_surface_t
*ret
;
212 imimage
= imlib_load_image_with_error_return(path
, &e
);
214 luaL_error(L
, "Cannot load image '%s': %s", path
, image_imlib_load_strerror(e
));
218 imlib_context_set_image(imimage
);
219 ret
= draw_surface_from_data(imlib_image_get_width(),
220 imlib_image_get_height(), imlib_image_get_data_for_reading_only());
221 imlib_free_image_and_decache();
225 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80