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
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.

77
image.c
View File

@ -75,26 +75,48 @@ image_imlib_load_strerror(Imlib_Load_Error e)
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.
* \return Data.
*/
static void
image_compute(image_t *image)
uint8_t *
image_getdata(image_t *image)
{
int size, i;
uint32_t *data;
double alpha;
uint8_t *dataimg;
if(image->isupdated)
return image->data;
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;
size = imlib_image_get_width() * imlib_image_get_height();
p_realloc(&image->data, size * 4);
dataimg = image->data;
@ -117,6 +139,10 @@ image_compute(image_t *image)
dataimg[0] = (data[i] & 0xff) * alpha; /* B */
#endif
}
image->isupdated = true;
return image->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);
image_t *image = image_new(globalconf.L);
image->image = imimage;
image_compute(image);
return 1;
}
@ -166,8 +191,6 @@ image_new_from_file(const char *filename)
image = image_new(globalconf.L);
image->image = imimage;
image_compute(image);
return 1;
}
@ -237,7 +260,7 @@ luaA_image_orientate(lua_State *L)
imlib_context_set_image(image->image);
imlib_image_orientate(orientation);
image_compute(image);
image->isupdated = false;
return 0;
}
@ -261,8 +284,6 @@ luaA_image_rotate(lua_State *L)
imlib_context_set_image(image->image);
new->image = imlib_create_rotated_image(angle);
image_compute(new);
return 1;
}
@ -290,8 +311,6 @@ luaA_image_crop(lua_State *L)
imlib_context_set_image(image->image);
new->image = imlib_create_cropped_image(x, y, w, h);
image_compute(new);
return 1;
}
@ -327,8 +346,6 @@ luaA_image_crop_and_scale(lua_State *L)
w, h,
dest_w, dest_h);
image_compute(new);
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_image_draw_pixel(x, y, 1);
image_compute(image);
image->isupdated = false;
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_image_draw_line(x1, y1, x2, y2, 0);
image_compute(image);
image->isupdated = false;
return 0;
}
@ -439,7 +456,7 @@ luaA_image_draw_rectangle(lua_State *L)
imlib_image_draw_rectangle(x, y, width, height);
else
imlib_image_fill_rectangle(x, y, width, height);
image_compute(image);
image->isupdated = false;
return 0;
}
@ -530,7 +547,7 @@ luaA_image_draw_rectangle_gradient(lua_State *L)
imlib_free_color_range();
image_compute(image);
image->isupdated = false;
return 0;
}
@ -574,7 +591,7 @@ luaA_image_draw_circle(lua_State *L)
imlib_image_draw_ellipse(x, y, ah, av);
else
imlib_image_fill_ellipse(x, y, ah, av);
image_compute(image);
image->isupdated = false;
return 0;
}
@ -629,14 +646,14 @@ luaA_image_insert(lua_State *L)
int xsrc = luaL_optnumber(L, 5, 0);
int ysrc = luaL_optnumber(L, 6, 0);
int wsrc = luaL_optnumber(L, 7, image_source->width);
int hsrc = luaL_optnumber(L, 8, image_source->height);
int wsrc = luaL_optnumber(L, 7, image_getwidth(image_source));
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 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);
@ -649,7 +666,7 @@ luaA_image_insert(lua_State *L)
* is the default */
hxoff, hyoff, vxoff, vyoff);
image_compute(image_target);
image_target->isupdated = false;
return 0;
}
@ -675,12 +692,10 @@ luaA_image_index(lua_State *L)
switch(a_tokenize(attr, len))
{
case A_TK_WIDTH:
imlib_context_set_image(image->image);
lua_pushnumber(L, imlib_image_get_width());
lua_pushnumber(L, image_getwidth(image));
break;
case A_TK_HEIGHT:
imlib_context_set_image(image->image);
lua_pushnumber(L, imlib_image_get_height());
lua_pushnumber(L, image_getheight(image));
break;
case A_TK_ALPHA:
imlib_context_set_image(image->image);

10
image.h
View File

@ -33,17 +33,19 @@ typedef struct
luaA_ref_array_t refs;
/** Imlib2 image */
Imlib_Image image;
/** Image width */
int width;
/** Image height */
int height;
/** Image data */
uint8_t *data;
/** Flag telling if the image is up to date or needs computing before
* drawing */
bool isupdated;
} image_t;
LUA_OBJECT_FUNCS(image_t, image, "image")
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
// 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)
{
int iwidth = image_getwidth(d->image);
int iheight = image_getheight(d->image);
if(d->resize)
{
double ratio = (double) height / d->image->height;
geometry.width = ratio * d->image->width;
double ratio = (double) height / iheight;
geometry.width = ratio * iwidth;
if(geometry.width > width)
{
geometry.width = 0;
@ -52,9 +54,9 @@ imagebox_geometry(widget_t *widget, screen_t *screen, int height, int width)
else
geometry.height = height;
}
else if(d->image->width <= width)
else if(iwidth <= width)
{
geometry.width = d->image->width;
geometry.width = iwidth;
geometry.height = height;
}
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);
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)
{
case AlignBottom:
y += geometry.height - d->image->height;
y += geometry.height - iheight;
break;
case AlignCenter:
y += (geometry.height - d->image->height) / 2;
y += (geometry.height - iheight) / 2;
break;
default:
break;

View File

@ -66,8 +66,10 @@ textbox_geometry(widget_t *widget, screen_t *screen, int height, int width)
geometry.width = width;
else if(d->bg_image)
{
double ratio = d->bg_resize ? (double) geometry.height / d->bg_image->height : 1;
geometry.width = MIN(width, MAX(d->extents.width + d->margin.left + d->margin.right, MAX(d->width, d->bg_image->width * ratio)));
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;
geometry.width = MIN(width, MAX(d->extents.width + d->margin.left + d->margin.right, MAX(d->width, bgi_width * ratio)));
}
else
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)
{
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 */
if(ratio * d->bg_image->width <= geometry.width)
if(ratio * bgi_width <= geometry.width)
{
int x = geometry.x;
int y = geometry.y;
switch(d->bg_align)
{
case AlignCenter:
x += (geometry.width - d->bg_image->width * ratio) / 2;
x += (geometry.width - bgi_width * ratio) / 2;
break;
case AlignRight:
x += geometry.width - d->bg_image->width * ratio;
x += geometry.width - bgi_width * ratio;
break;
case AlignBottom:
y += geometry.height - d->bg_image->height * ratio;
y += geometry.height - bgi_height * ratio;
break;
case AlignMiddle:
y += (geometry.height - d->bg_image->height * ratio) / 2;
y += (geometry.height - bgi_height * ratio) / 2;
break;
default:
break;