forked from awesomeWM/awesome
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimage.c
More file actions
363 lines (312 loc) · 10.1 KB
/
Copy pathimage.c
File metadata and controls
363 lines (312 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
/*
* image.c - image object
*
* Copyright © 2008 Julien Danjou <julien@danjou.info>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "structs.h"
extern awesome_t globalconf;
DO_LUA_NEW(extern, image_t, image, "image", image_ref)
DO_LUA_GC(image_t, image, "image", image_unref)
DO_LUA_EQ(image_t, image, "image")
static const char *
image_imlib_load_strerror(Imlib_Load_Error e)
{
switch(e)
{
case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST:
return "no such file or directory";
case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY:
return "file is a directory";
case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ:
return "read permission denied";
case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT:
return "no loader for file format";
case IMLIB_LOAD_ERROR_PATH_TOO_LONG:
return "path too long";
case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT:
return "path component non existant";
case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY:
return "path compoment not a directory";
case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE:
return "path points oustide address space";
case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS:
return "too many symbolic links";
case IMLIB_LOAD_ERROR_OUT_OF_MEMORY:
return "out of memory";
case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS:
return "out of file descriptors";
case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE:
return "write permission denied";
case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE:
return "out of disk space";
case IMLIB_LOAD_ERROR_UNKNOWN:
return "unknown error, that's really bad";
case IMLIB_LOAD_ERROR_NONE:
return "no error, oops";
}
return "unknown error";
}
/** Recompute the ARGB32 data from an image.
* \param image The image.
* \return Data.
*/
static void
image_compute(image_t *image)
{
int size, i;
uint32_t *data;
double alpha;
uint8_t *dataimg;
imlib_context_set_image(image->image);
data = imlib_image_get_data_for_reading_only();
image->width = imlib_image_get_width();
image->height = imlib_image_get_height();
size = image->width * image->height;
p_delete(&image->data);
image->data = dataimg = p_new(uint8_t, size * 4);
for(i = 0; i < size; i++, dataimg += 4)
{
dataimg[3] = (data[i] >> 24) & 0xff; /* A */
/* cairo wants pre-multiplied alpha */
alpha = dataimg[3] / 255.0;
dataimg[2] = ((data[i] >> 16) & 0xff) * alpha; /* R */
dataimg[1] = ((data[i] >> 8) & 0xff) * alpha; /* G */
dataimg[0] = (data[i] & 0xff) * alpha; /* B */
}
}
/** Create a new image from ARGB32 data.
* \param width The image width.
* \param height The image height.
* \param data The image data.
* \return A brand new image.
*/
image_t *
image_new_from_argb32(int width, int height, uint32_t *data)
{
Imlib_Image imimage;
image_t *image = NULL;
if((imimage = imlib_create_image_using_copied_data(width, height, data)))
{
image = p_new(image_t, 1);
image->image = imimage;
image_compute(image);
}
return image;
}
/** Load an image from filename.
* \param filename The image file to load.
* \return A new image.
*/
image_t *
image_new_from_file(const char *filename)
{
Imlib_Image imimage;
Imlib_Load_Error e = IMLIB_LOAD_ERROR_NONE;
image_t *image;
if(!filename)
return NULL;
if(!(imimage = imlib_load_image_with_error_return(filename, &e)))
{
warn("cannot load image %s: %s", filename, image_imlib_load_strerror(e));
return NULL;
}
image = p_new(image_t, 1);
image->image = imimage;
image_compute(image);
return image;
}
/** Create a new image object.
* \param L The Lua stack.
* \return The number of elements pushed on stack.
* \luastack
* \lparam The image path, or nil to create an empty image.
* \lparam The image width if nil was set as first arg.
* \lparam The image height if nil was set as first arg.
* \lreturn An image object.
*/
static int
luaA_image_new(lua_State *L)
{
const char *filename;
if((filename = lua_tostring(L, 2)))
{
image_t *image;
if((image = image_new_from_file(filename)))
return luaA_image_userdata_new(L, image);
}
else if(lua_isnil(L, 2))
{
int width = luaL_checknumber(L, 3);
int height = luaL_checknumber(L, 4);
if(width <= 0 || height <= 0)
luaL_error(L, "request image has invalid size");
Imlib_Image imimage = imlib_create_image(width, height);
image_t *image = p_new(image_t, 1);
image->image = imimage;
image_compute(image);
return luaA_image_userdata_new(L, image);
}
return 0;
}
/** Create a new image object from ARGB32 data.
* \param L The Lua stack.
* \return The number of elements pushed on stack.
* \luastack
* \lparam The image width.
* \lparam The image height.
* \lparam The image data as a string in ARGB32 format.
* \lreturn An image object.
*/
static int
luaA_image_argb32_new(lua_State *L)
{
size_t len;
image_t *image;
unsigned int width = luaL_checknumber(L, 1);
unsigned int height = luaL_checknumber(L, 2);
const char *data = luaL_checklstring(L, 3, &len);
if(width * height * 4 != len)
luaL_error(L, "string size does not match image size");
if((image = image_new_from_argb32(width, height, (uint32_t *) data)))
return luaA_image_userdata_new(L, image);
return 0;
}
/** Rotate an image with specified angle radians and return a new image.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lvalue An image.
* \lparam The angle in radians.
* \lreturn A rotated image.
*/
static int
luaA_image_rotate(lua_State *L)
{
image_t **image = luaA_checkudata(L, 1, "image"), *new;
double angle = luaL_checknumber(L, 2);
new = p_new(image_t, 1);
imlib_context_set_image((*image)->image);
new->image = imlib_create_rotated_image(angle);
image_compute(new);
return luaA_image_userdata_new(L, new);
}
/** Crop an image to the given rectangle.
* \return The number of elements pushed on stack.
* \luastack
* \lvalue An image.
* \lparam The top left x coordinate of the rectangle.
* \lparam The top left y coordinate of the rectangle.
* \lparam The width of the rectangle.
* \lparam The height of the rectangle.
* \lreturn A cropped image.
*/
static int
luaA_image_crop(lua_State *L)
{
image_t **image = luaA_checkudata(L, 1, "image"), *new;
int x = luaL_checkint(L, 2);
int y = luaL_checkint(L, 3);
int w = luaL_checkint(L, 4);
int h = luaL_checkint(L, 5);
new = p_new(image_t, 1);
imlib_context_set_image((*image)->image);
new->image = imlib_create_cropped_image(x, y, w, h);
image_compute(new);
return luaA_image_userdata_new(L, new);
}
/** Crop the image to the given rectangle and scales it.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lvalue An image.
* \lparam The top left x coordinate of the source rectangle.
* \lparam The top left y coordinate of the source rectangle.
* \lparam The width of the source rectangle.
* \lparam The height of the source rectangle.
* \lparam The width of the destination rectangle.
* \lparam The height of the destination rectangle.
* \lreturn A cropped image.
*/
static int
luaA_image_crop_and_scale(lua_State *L)
{
image_t **image = luaA_checkudata(L, 1, "image"), *new;
int source_x = luaL_checkint(L, 2);
int source_y = luaL_checkint(L, 3);
int w = luaL_checkint(L, 4);
int h = luaL_checkint(L, 5);
int dest_w = luaL_checkint(L, 6);
int dest_h = luaL_checkint(L, 7);
new = p_new(image_t, 1);
imlib_context_set_image((*image)->image);
new->image = imlib_create_cropped_scaled_image(source_x,
source_y,
w, h,
dest_w, dest_h);
image_compute(new);
return luaA_image_userdata_new(L, new);
}
/** Image object.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lvalue An image
* \lfield width The image width.
* \lfield height The image height.
*/
static int
luaA_image_index(lua_State *L)
{
if(luaA_usemetatable(L, 1, 2))
return 1;
image_t **image = luaA_checkudata(L, 1, "image");
size_t len;
const char *attr = luaL_checklstring(L, 2, &len);
switch(a_tokenize(attr, len))
{
case A_TK_WIDTH:
imlib_context_set_image((*image)->image);
lua_pushnumber(L, imlib_image_get_width());
break;
case A_TK_HEIGHT:
imlib_context_set_image((*image)->image);
lua_pushnumber(L, imlib_image_get_height());
break;
default:
return 0;
}
return 1;
}
const struct luaL_reg awesome_image_methods[] =
{
{ "__call", luaA_image_new },
{ "argb32", luaA_image_argb32_new },
{ NULL, NULL }
};
const struct luaL_reg awesome_image_meta[] =
{
{ "__index", luaA_image_index },
{ "rotate", luaA_image_rotate },
{ "crop", luaA_image_crop },
{ "crop_and_scale", luaA_image_crop_and_scale },
{ "__gc", luaA_image_gc },
{ "__eq", luaA_image_eq },
{ "__tostring", luaA_image_tostring },
{ NULL, NULL }
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80