From 86fe1e8b5cdfd536fb19018fc15d9088e13bf676 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Sun, 24 May 2009 01:54:15 +0000 Subject: Lua: add image handling + some other wrappers git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21063 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/lua/rocklib.c | 282 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 281 insertions(+), 1 deletion(-) diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index c99400c938..7daed0c93d 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c @@ -38,6 +38,136 @@ * and returns the number of results. Any other value in the stack below the results will be properly * discarded by Lua. Like a Lua function, a C function called by Lua can also return many results. */ + + +/* + * ----------------------------- + * + * Rockbox Lua image wrapper + * + * ----------------------------- + */ + +#define ROCKLUA_IMAGE "rb.image" +struct rocklua_image +{ + int width; + int height; + fb_data *data; +}; + +static void rli_wrap(lua_State *L, fb_data *src, int width, int height) +{ + struct rocklua_image *a = (struct rocklua_image *)lua_newuserdata(L, sizeof(struct rocklua_image)); + + luaL_getmetatable(L, ROCKLUA_IMAGE); + lua_setmetatable(L, -2); + + a->width = width; + a->height = height; + a->data = src; +} + +static int rli_new(lua_State *L) +{ + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + size_t nbytes = sizeof(struct rocklua_image) + (width - 1)*(height - 1)*sizeof(fb_data); + struct rocklua_image *a = (struct rocklua_image *)lua_newuserdata(L, nbytes); + + luaL_getmetatable(L, ROCKLUA_IMAGE); + lua_setmetatable(L, -2); + + a->width = width; + a->height = height; + return 1; +} + +static struct rocklua_image* rli_checktype(lua_State *L, int arg) +{ + void *ud = luaL_checkudata(L, arg, ROCKLUA_IMAGE); + luaL_argcheck(L, ud != NULL, arg, "'" ROCKLUA_IMAGE "' expected"); + return (struct rocklua_image*) ud; +} + +static int rli_width(lua_State *L) +{ + struct rocklua_image *a = rli_checktype(L, 1); + lua_pushnumber(L, a->width); + return 1; +} + +static int rli_height(lua_State *L) +{ + struct rocklua_image *a = rli_checktype(L, 1); + lua_pushnumber(L, a->height); + return 1; +} + +static fb_data* rli_element(lua_State *L) +{ + struct rocklua_image *a = rli_checktype(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + + luaL_argcheck(L, 1 <= x && x <= a->width, 2, + "index out of range"); + luaL_argcheck(L, 1 <= y && y <= a->height, 3, + "index out of range"); + + /* return element address */ + return &a->data[a->height * (y - 1) + (x - 1)]; +} + +static int rli_set(lua_State *L) +{ + fb_data newvalue = (fb_data) luaL_checknumber(L, 4); + *rli_element(L) = newvalue; + return 0; +} + +static int rli_get(lua_State *L) +{ + lua_pushnumber(L, *rli_element(L)); + return 1; +} + +static int rli_tostring(lua_State *L) +{ + struct rocklua_image *a = rli_checktype(L, 1); + lua_pushfstring(L, ROCKLUA_IMAGE ": %dx%d", a->width, a->height); + return 1; +} + +static const struct luaL_reg rli_lib [] = +{ + {"__tostring", rli_tostring}, + {"set", rli_set}, + {"get", rli_get}, + {"width", rli_width}, + {"height", rli_height}, + {NULL, NULL} +}; + +static inline void rli_init(lua_State *L) +{ + luaL_newmetatable(L, ROCKLUA_IMAGE); + + lua_pushstring(L, "__index"); + lua_pushvalue(L, -2); /* pushes the metatable */ + lua_settable(L, -3); /* metatable.__index = metatable */ + + luaL_register(L, NULL, rli_lib); +} + +/* + * ----------------------------- + * + * Rockbox wrappers start here! + * + * ----------------------------- + */ + #define RB_WRAP(M) static int rock_##M(lua_State *L) RB_WRAP(splash) @@ -55,6 +185,16 @@ RB_WRAP(lcd_update) return 0; } +RB_WRAP(lcd_update_rect) +{ + int x = luaL_checkint(L, 1); + int y = luaL_checkint(L, 2); + int width = luaL_checkint(L, 3); + int height = luaL_checkint(L, 4); + rb->lcd_update_rect(x, y, width, height); + return 0; +} + RB_WRAP(lcd_clear_display) { (void)L; @@ -97,6 +237,12 @@ RB_WRAP(lcd_stop_scroll) } #ifdef HAVE_LCD_BITMAP +RB_WRAP(lcd_framebuffer) +{ + rli_wrap(L, rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT); + return 1; +} + RB_WRAP(lcd_set_drawmode) { int drawmode = luaL_checkint(L, 1); @@ -179,7 +325,106 @@ RB_WRAP(lcd_fillrect) rb->lcd_fillrect(x, y, width, height); return 0; } -#endif + +#if LCD_DEPTH > 1 +RB_WRAP(lcd_set_foreground) +{ + unsigned foreground = luaL_checkint(L, 1); + rb->lcd_set_foreground(foreground); + return 0; +} + +RB_WRAP(lcd_get_foreground) +{ + unsigned result = rb->lcd_get_foreground(); + lua_pushinteger(L, result); + return 1; +} + +RB_WRAP(lcd_set_background) +{ + unsigned background = luaL_checkint(L, 1); + rb->lcd_set_background(background); + return 0; +} + +RB_WRAP(lcd_get_background) +{ + unsigned result = rb->lcd_get_background(); + lua_pushinteger(L, result); + return 1; +} + +RB_WRAP(lcd_bitmap_part) +{ + struct rocklua_image *src = rli_checktype(L, 1); + int src_x = luaL_checkint(L, 2); + int src_y = luaL_checkint(L, 3); + int stride = luaL_checkint(L, 4); + int x = luaL_checkint(L, 5); + int y = luaL_checkint(L, 6); + int width = luaL_checkint(L, 7); + int height = luaL_checkint(L, 8); + + rb->lcd_bitmap_part(src->data, src_x, src_y, stride, x, y, width, height); + return 0; +} + +RB_WRAP(lcd_bitmap) +{ + struct rocklua_image *src = rli_checktype(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int width = luaL_checkint(L, 4); + int height = luaL_checkint(L, 5); + + rb->lcd_bitmap(src->data, x, y, width, height); + return 0; +} + +RB_WRAP(lcd_get_backdrop) +{ + fb_data* backdrop = rb->lcd_get_backdrop(); + if(backdrop == NULL) + return 0; + else + { + rli_wrap(L, backdrop, LCD_WIDTH, LCD_HEIGHT); + return 1; + } +} +#endif /* LCD_DEPTH > 1 */ + +#if LCD_DEPTH == 16 +RB_WRAP(lcd_bitmap_transparent_part) +{ + struct rocklua_image *src = rli_checktype(L, 1); + int src_x = luaL_checkint(L, 2); + int src_y = luaL_checkint(L, 3); + int stride = luaL_checkint(L, 4); + int x = luaL_checkint(L, 5); + int y = luaL_checkint(L, 6); + int width = luaL_checkint(L, 7); + int height = luaL_checkint(L, 8); + + rb->lcd_bitmap_transparent_part(src->data, src_x, src_y, stride, x, y, width, height); + return 0; +} + +RB_WRAP(lcd_bitmap_transparent) +{ + struct rocklua_image *src = rli_checktype(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int width = luaL_checkint(L, 4); + int height = luaL_checkint(L, 5); + + rb->lcd_bitmap_transparent(src->data, x, y, width, height); + return 0; +} +#endif /* LCD_DEPTH == 16 */ + +#endif /* defined(LCD_BITMAP) */ RB_WRAP(yield) { @@ -432,18 +677,34 @@ RB_WRAP(file_exists) return 1; } +RB_WRAP(font_getstringsize) +{ + const unsigned char* str = luaL_checkstring(L, 1); + int fontnumber = luaL_checkint(L, 2); + int w, h; + + int result = rb->font_getstringsize(str, &w, &h, fontnumber); + lua_pushinteger(L, result); + lua_pushinteger(L, w); + lua_pushinteger(L, h); + + return 3; +} + #define R(NAME) {#NAME, rock_##NAME} static const luaL_Reg rocklib[] = { /* Graphics */ R(lcd_clear_display), R(lcd_update), + R(lcd_update_rect), R(lcd_puts), R(lcd_putsxy), R(lcd_puts_scroll), R(lcd_stop_scroll), R(splash), #ifdef HAVE_LCD_BITMAP + R(lcd_framebuffer), R(lcd_set_drawmode), R(lcd_get_drawmode), R(lcd_setfont), @@ -453,6 +714,19 @@ static const luaL_Reg rocklib[] = R(lcd_vline), R(lcd_drawrect), R(lcd_fillrect), +#if LCD_DEPTH > 1 + R(lcd_set_foreground), + R(lcd_get_foreground), + R(lcd_set_background), + R(lcd_get_background), + R(lcd_get_backdrop), + R(lcd_bitmap_part), + R(lcd_bitmap), +#endif +#if LCD_DEPTH == 16 + R(lcd_bitmap_transparent_part), + R(lcd_bitmap_transparent), +#endif #endif /* File handling */ @@ -498,6 +772,10 @@ static const luaL_Reg rocklib[] = R(backlight_set_brightness), #endif + R(font_getstringsize), + + {"new_image", rli_new}, + {NULL, NULL} }; #undef R @@ -525,6 +803,8 @@ LUALIB_API int luaopen_rock(lua_State *L) RB_CONSTANT(SEEK_CUR); RB_CONSTANT(SEEK_END); + rli_init(L); + return 1; } -- cgit v1.2.3