image: only compute when needed

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-05-04 10:34:54 +02:00
parent 1e6d4747be
commit 45c2ac38a4
5 changed files with 75 additions and 51 deletions

2
draw.c
View File

@ -598,7 +598,7 @@ draw_image_from_argb_data(draw_context_t *ctx, int x, int y, int w, int h,
void void
draw_image(draw_context_t *ctx, int x, int y, double ratio, image_t *image) draw_image(draw_context_t *ctx, int x, int y, double ratio, image_t *image)
{ {
draw_image_from_argb_data(ctx, x, y, image->width, image->height, ratio, image->data); draw_image_from_argb_data(ctx, x, y, image_getwidth(image), image_getheight(image), ratio, image_getdata(image));
} }
/** Rotate a pixmap. /** Rotate a pixmap.

77
image.c
View File

@ -75,26 +75,48 @@ image_imlib_load_strerror(Imlib_Load_Error e)
return "unknown error"; return "unknown error";
} }
/** Recompute the ARGB32 data from an image. /** Get image width.
* \param image The image.
* \return The image width in pixel.
*/
int
image_getwidth(image_t *image)
{
imlib_context_set_image(image->image);
return imlib_image_get_width();
}
/** Get image height.
* \param image The image.
* \return The image height in pixel.
*/
int
image_getheight(image_t *image)
{
imlib_context_set_image(image->image);
return imlib_image_get_height();
}
/** Get the ARGB32 data from an image.
* \param image The image. * \param image The image.
* \return Data. * \return Data.
*/ */
static void uint8_t *
image_compute(image_t *image) image_getdata(image_t *image)
{ {
int size, i; int size, i;
uint32_t *data; uint32_t *data;
double alpha; double alpha;
uint8_t *dataimg; uint8_t *dataimg;
if(image->isupdated)
return image->data;
imlib_context_set_image(image->image); imlib_context_set_image(image->image);
data = imlib_image_get_data_for_reading_only(); data = imlib_image_get_data_for_reading_only();
image->width = imlib_image_get_width(); size = imlib_image_get_width() * imlib_image_get_height();
image->height = imlib_image_get_height();
size = image->width * image->height;
p_realloc(&image->data, size * 4); p_realloc(&image->data, size * 4);
dataimg = image->data; dataimg = image->data;
@ -117,6 +139,10 @@ image_compute(image_t *image)
dataimg[0] = (data[i] & 0xff) * alpha; /* B */ dataimg[0] = (data[i] & 0xff) * alpha; /* B */
#endif #endif
} }
image->isupdated = true;
return image->data;
} }
/** Create a new image from ARGB32 data. /** Create a new image from ARGB32 data.
@ -136,7 +162,6 @@ image_new_from_argb32(int width, int height, uint32_t *data)
imlib_image_set_has_alpha(true); imlib_image_set_has_alpha(true);
image_t *image = image_new(globalconf.L); image_t *image = image_new(globalconf.L);
image->image = imimage; image->image = imimage;
image_compute(image);
return 1; return 1;
} }
@ -166,8 +191,6 @@ image_new_from_file(const char *filename)
image = image_new(globalconf.L); image = image_new(globalconf.L);
image->image = imimage; image->image = imimage;
image_compute(image);
return 1; return 1;
} }
@ -237,7 +260,7 @@ luaA_image_orientate(lua_State *L)
imlib_context_set_image(image->image); imlib_context_set_image(image->image);
imlib_image_orientate(orientation); imlib_image_orientate(orientation);
image_compute(image); image->isupdated = false;
return 0; return 0;
} }
@ -261,8 +284,6 @@ luaA_image_rotate(lua_State *L)
imlib_context_set_image(image->image); imlib_context_set_image(image->image);
new->image = imlib_create_rotated_image(angle); new->image = imlib_create_rotated_image(angle);
image_compute(new);
return 1; return 1;
} }
@ -290,8 +311,6 @@ luaA_image_crop(lua_State *L)
imlib_context_set_image(image->image); imlib_context_set_image(image->image);
new->image = imlib_create_cropped_image(x, y, w, h); new->image = imlib_create_cropped_image(x, y, w, h);
image_compute(new);
return 1; return 1;
} }
@ -327,8 +346,6 @@ luaA_image_crop_and_scale(lua_State *L)
w, h, w, h,
dest_w, dest_h); dest_w, dest_h);
image_compute(new);
return 1; return 1;
} }
@ -360,7 +377,7 @@ luaA_image_draw_pixel(lua_State *L)
imlib_context_set_color(color.red, color.green, color.blue, color.alpha); imlib_context_set_color(color.red, color.green, color.blue, color.alpha);
imlib_image_draw_pixel(x, y, 1); imlib_image_draw_pixel(x, y, 1);
image_compute(image); image->isupdated = false;
return 0; return 0;
} }
@ -396,7 +413,7 @@ luaA_image_draw_line(lua_State *L)
imlib_context_set_color(color.red, color.green, color.blue, color.alpha); imlib_context_set_color(color.red, color.green, color.blue, color.alpha);
imlib_image_draw_line(x1, y1, x2, y2, 0); imlib_image_draw_line(x1, y1, x2, y2, 0);
image_compute(image); image->isupdated = false;
return 0; return 0;
} }
@ -439,7 +456,7 @@ luaA_image_draw_rectangle(lua_State *L)
imlib_image_draw_rectangle(x, y, width, height); imlib_image_draw_rectangle(x, y, width, height);
else else
imlib_image_fill_rectangle(x, y, width, height); imlib_image_fill_rectangle(x, y, width, height);
image_compute(image); image->isupdated = false;
return 0; return 0;
} }
@ -530,7 +547,7 @@ luaA_image_draw_rectangle_gradient(lua_State *L)
imlib_free_color_range(); imlib_free_color_range();
image_compute(image); image->isupdated = false;
return 0; return 0;
} }
@ -574,7 +591,7 @@ luaA_image_draw_circle(lua_State *L)
imlib_image_draw_ellipse(x, y, ah, av); imlib_image_draw_ellipse(x, y, ah, av);
else else
imlib_image_fill_ellipse(x, y, ah, av); imlib_image_fill_ellipse(x, y, ah, av);
image_compute(image); image->isupdated = false;
return 0; return 0;
} }
@ -629,14 +646,14 @@ luaA_image_insert(lua_State *L)
int xsrc = luaL_optnumber(L, 5, 0); int xsrc = luaL_optnumber(L, 5, 0);
int ysrc = luaL_optnumber(L, 6, 0); int ysrc = luaL_optnumber(L, 6, 0);
int wsrc = luaL_optnumber(L, 7, image_source->width); int wsrc = luaL_optnumber(L, 7, image_getwidth(image_source));
int hsrc = luaL_optnumber(L, 8, image_source->height); int hsrc = luaL_optnumber(L, 8, image_getheight(image_source));
int hxoff = luaL_optnumber(L, 9, image_source->width); int hxoff = luaL_optnumber(L, 9, image_getwidth(image_source));
int hyoff = luaL_optnumber(L, 10, 0); int hyoff = luaL_optnumber(L, 10, 0);
int vxoff = luaL_optnumber(L, 11, 0); int vxoff = luaL_optnumber(L, 11, 0);
int vyoff = luaL_optnumber(L, 12, image_source->height); int vyoff = luaL_optnumber(L, 12, image_getheight(image_source));
imlib_context_set_image(image_target->image); imlib_context_set_image(image_target->image);
@ -649,7 +666,7 @@ luaA_image_insert(lua_State *L)
* is the default */ * is the default */
hxoff, hyoff, vxoff, vyoff); hxoff, hyoff, vxoff, vyoff);
image_compute(image_target); image_target->isupdated = false;
return 0; return 0;
} }
@ -675,12 +692,10 @@ luaA_image_index(lua_State *L)
switch(a_tokenize(attr, len)) switch(a_tokenize(attr, len))
{ {
case A_TK_WIDTH: case A_TK_WIDTH:
imlib_context_set_image(image->image); lua_pushnumber(L, image_getwidth(image));
lua_pushnumber(L, imlib_image_get_width());
break; break;
case A_TK_HEIGHT: case A_TK_HEIGHT:
imlib_context_set_image(image->image); lua_pushnumber(L, image_getheight(image));
lua_pushnumber(L, imlib_image_get_height());
break; break;
case A_TK_ALPHA: case A_TK_ALPHA:
imlib_context_set_image(image->image); imlib_context_set_image(image->image);

10
image.h
View File

@ -33,17 +33,19 @@ typedef struct
luaA_ref_array_t refs; luaA_ref_array_t refs;
/** Imlib2 image */ /** Imlib2 image */
Imlib_Image image; Imlib_Image image;
/** Image width */
int width;
/** Image height */
int height;
/** Image data */ /** Image data */
uint8_t *data; uint8_t *data;
/** Flag telling if the image is up to date or needs computing before
* drawing */
bool isupdated;
} image_t; } image_t;
LUA_OBJECT_FUNCS(image_t, image, "image") LUA_OBJECT_FUNCS(image_t, image, "image")
int image_new_from_argb32(int, int, uint32_t *); int image_new_from_argb32(int, int, uint32_t *);
uint8_t * image_getdata(image_t *);
int image_getwidth(image_t *);
int image_getheight(image_t *);
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -40,10 +40,12 @@ imagebox_geometry(widget_t *widget, screen_t *screen, int height, int width)
if(d->image) if(d->image)
{ {
int iwidth = image_getwidth(d->image);
int iheight = image_getheight(d->image);
if(d->resize) if(d->resize)
{ {
double ratio = (double) height / d->image->height; double ratio = (double) height / iheight;
geometry.width = ratio * d->image->width; geometry.width = ratio * iwidth;
if(geometry.width > width) if(geometry.width > width)
{ {
geometry.width = 0; geometry.width = 0;
@ -52,9 +54,9 @@ imagebox_geometry(widget_t *widget, screen_t *screen, int height, int width)
else else
geometry.height = height; geometry.height = height;
} }
else if(d->image->width <= width) else if(iwidth <= width)
{ {
geometry.width = d->image->width; geometry.width = iwidth;
geometry.height = height; geometry.height = height;
} }
else else
@ -91,14 +93,15 @@ imagebox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry, wibox_t *p
draw_rectangle(ctx, geometry, 1.0, true, &d->bg); draw_rectangle(ctx, geometry, 1.0, true, &d->bg);
int y = geometry.y; int y = geometry.y;
double ratio = d->resize ? (double) geometry.height / d->image->height : 1; int iheight = image_getheight(d->image);
double ratio = d->resize ? (double) geometry.height / iheight : 1;
switch(d->valign) switch(d->valign)
{ {
case AlignBottom: case AlignBottom:
y += geometry.height - d->image->height; y += geometry.height - iheight;
break; break;
case AlignCenter: case AlignCenter:
y += (geometry.height - d->image->height) / 2; y += (geometry.height - iheight) / 2;
break; break;
default: default:
break; break;

View File

@ -66,8 +66,10 @@ textbox_geometry(widget_t *widget, screen_t *screen, int height, int width)
geometry.width = width; geometry.width = width;
else if(d->bg_image) else if(d->bg_image)
{ {
double ratio = d->bg_resize ? (double) geometry.height / d->bg_image->height : 1; int bgi_height = image_getheight(d->bg_image);
geometry.width = MIN(width, MAX(d->extents.width + d->margin.left + d->margin.right, MAX(d->width, d->bg_image->width * ratio))); int bgi_width = image_getwidth(d->bg_image);
double ratio = d->bg_resize ? (double) geometry.height / bgi_height : 1;
geometry.width = MIN(width, MAX(d->extents.width + d->margin.left + d->margin.right, MAX(d->width, bgi_width * ratio)));
} }
else else
geometry.width = MIN(d->extents.width + d->margin.left + d->margin.right, width); geometry.width = MIN(d->extents.width + d->margin.left + d->margin.right, width);
@ -95,25 +97,27 @@ textbox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry, wibox_t *p)
if(d->bg_image) if(d->bg_image)
{ {
double ratio = d->bg_resize ? (double) geometry.height / d->bg_image->height : 1; int bgi_height = image_getheight(d->bg_image);
int bgi_width = image_getwidth(d->bg_image);
double ratio = d->bg_resize ? (double) geometry.height / bgi_height : 1;
/* check there is enough space to draw the image */ /* check there is enough space to draw the image */
if(ratio * d->bg_image->width <= geometry.width) if(ratio * bgi_width <= geometry.width)
{ {
int x = geometry.x; int x = geometry.x;
int y = geometry.y; int y = geometry.y;
switch(d->bg_align) switch(d->bg_align)
{ {
case AlignCenter: case AlignCenter:
x += (geometry.width - d->bg_image->width * ratio) / 2; x += (geometry.width - bgi_width * ratio) / 2;
break; break;
case AlignRight: case AlignRight:
x += geometry.width - d->bg_image->width * ratio; x += geometry.width - bgi_width * ratio;
break; break;
case AlignBottom: case AlignBottom:
y += geometry.height - d->bg_image->height * ratio; y += geometry.height - bgi_height * ratio;
break; break;
case AlignMiddle: case AlignMiddle:
y += (geometry.height - d->bg_image->height * ratio) / 2; y += (geometry.height - bgi_height * ratio) / 2;
break; break;
default: default:
break; break;