luaA_object_emit_signal: Fix a crash on non-objects
[awesome.git] / draw.c
blob16e63c466b5b52acd2ca34321ff735ff8998148c
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 "globalconf.h"
33 #include "screen.h"
35 #include "common/xutil.h"
37 /** Convert text from any charset to UTF-8 using iconv.
38 * \param iso The ISO string to convert.
39 * \param len The string size.
40 * \param dest The destination pointer. Memory will be allocated, up to you to
41 * free, like any char *.
42 * \param dlen The destination length, can be NULL.
43 * \return True if conversion was done.
45 bool
46 draw_iso2utf8(const char *iso, size_t len, char **dest, ssize_t *dlen)
48 static iconv_t iso2utf8 = (iconv_t) -1;
49 static int8_t dont_need_convert = -1;
51 if(dont_need_convert == -1)
52 dont_need_convert = A_STREQ(nl_langinfo(CODESET), "UTF-8");
54 if(!len || dont_need_convert)
55 return false;
57 if(iso2utf8 == (iconv_t) -1)
59 iso2utf8 = iconv_open("UTF-8", nl_langinfo(CODESET));
60 if(iso2utf8 == (iconv_t) -1)
62 if(errno == EINVAL)
63 warn("unable to convert text from %s to UTF-8, not available",
64 nl_langinfo(CODESET));
65 else
66 warn("unable to convert text: %s", strerror(errno));
68 return false;
72 size_t orig_utf8len, utf8len;
73 char *utf8;
75 orig_utf8len = utf8len = 2 * len + 1;
76 utf8 = *dest = p_new(char, utf8len);
78 if(iconv(iso2utf8, (char **) &iso, &len, &utf8, &utf8len) == (size_t) -1)
80 warn("text conversion failed: %s", strerror(errno));
81 p_delete(dest);
82 return false;
85 if(dlen)
86 *dlen = orig_utf8len - utf8len;
88 return true;
91 static cairo_user_data_key_t data_key;
93 static inline void
94 free_data(void *data)
96 p_delete(&data);
99 /** Create a surface object on the lua stack from this image data.
100 * \param L The lua stack.
101 * \param width The width of the image.
102 * \param height The height of the image
103 * \param data The image's data in ARGB format, will be copied by this function.
104 * \return Number of items pushed on the lua stack.
107 luaA_surface_from_data(lua_State *L, int width, int height, uint32_t *data)
109 unsigned long int len = width * height;
110 unsigned long int i;
111 uint32_t *buffer = p_new(uint32_t, len);
112 cairo_surface_t *surface;
114 /* Cairo wants premultiplied alpha, meh :( */
115 for(i = 0; i < len; i++)
117 uint8_t a = (data[i] >> 24) & 0xff;
118 double alpha = a / 255.0;
119 uint8_t r = ((data[i] >> 16) & 0xff) * alpha;
120 uint8_t g = ((data[i] >> 8) & 0xff) * alpha;
121 uint8_t b = ((data[i] >> 0) & 0xff) * alpha;
122 buffer[i] = (a << 24) | (r << 16) | (g << 8) | b;
125 surface =
126 cairo_image_surface_create_for_data((unsigned char *) buffer,
127 CAIRO_FORMAT_ARGB32,
128 width,
129 height,
130 width*4);
131 /* This makes sure that buffer will be freed */
132 cairo_surface_set_user_data(surface, &data_key, buffer, &free_data);
134 /* This will increase the reference count of the surface */
135 int ret = oocairo_surface_push(globalconf.L, surface);
136 /* So we have to drop our own reference */
137 cairo_surface_destroy(surface);
139 return ret;
142 /** Duplicate the specified image surface.
143 * \param surface The surface to copy
144 * \return A pointer to a new cairo image surface.
146 cairo_surface_t *
147 draw_dup_image_surface(cairo_surface_t *surface)
149 cairo_surface_t *res = cairo_image_surface_create(
150 cairo_image_surface_get_format(surface),
151 cairo_image_surface_get_width(surface),
152 cairo_image_surface_get_height(surface));
154 cairo_t *cr = cairo_create(res);
155 cairo_set_source_surface(cr, surface, 0, 0);
156 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
157 cairo_paint(cr);
158 cairo_destroy(cr);
160 return res;
163 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80