diff --git a/draw.c b/draw.c index 57823bc9..db9cdb3d 100644 --- a/draw.c +++ b/draw.c @@ -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. diff --git a/image.c b/image.c index fb1e5a02..a9d54a3a 100644 --- a/image.c +++ b/image.c @@ -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); diff --git a/image.h b/image.h index b3669ec9..03d52be6 100644 --- a/image.h +++ b/image.h @@ -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 diff --git a/widgets/imagebox.c b/widgets/imagebox.c index a9598fd9..f1db63a9 100644 --- a/widgets/imagebox.c +++ b/widgets/imagebox.c @@ -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; diff --git a/widgets/textbox.c b/widgets/textbox.c index ed508a88..97107560 100644 --- a/widgets/textbox.c +++ b/widgets/textbox.c @@ -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;