From df8233e4abbd0d626158abc5388957cc28b06c50 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sat, 27 Oct 2018 06:24:27 -0400 Subject: Lua expand multiple screen support Some of the lcd functions had support for multiple screens but this wasn't very safe since the screen number wasn't bounded within the screens[] array This adds support for all the lcd functions along with checking that screen# is bounded properly, adds around 600 bytes to devices with a remote screen devices without a remote screen lock to SCREEN_MAIN Change-Id: I618bbc7b3919c7b0ff375fb2d71949d7cab43c87 --- apps/plugins/lua/rocklib.c | 87 +---------- apps/plugins/lua/rocklib_aux.pl | 8 ++ apps/plugins/lua/rocklib_img.c | 309 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 303 insertions(+), 101 deletions(-) (limited to 'apps/plugins/lua') diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index 80124d2165..c9242d99bd 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c @@ -56,66 +56,6 @@ #define RB_WRAP(func) static int rock_##func(lua_State UNUSED_ATTR *L) #define SIMPLE_VOID_WRAPPER(func) RB_WRAP(func) { (void)L; func(); return 0; } -/* Helper function for opt_viewport */ -static void check_tablevalue(lua_State *L, - const char* key, - int tablepos, - void* res, - bool is_unsigned) -{ - lua_getfield(L, tablepos, key); /* Find table[key] */ - - int val = lua_tointeger(L, -1); - - if(is_unsigned) - *(unsigned*)res = (unsigned) val; - else - *(int*)res = val; - - lua_pop(L, 1); /* Pop the value off the stack */ -} - -static inline struct viewport* opt_viewport(lua_State *L, - int narg, - struct viewport* vp, - struct viewport* alt) -{ - if(lua_isnoneornil(L, narg)) - return alt; - - luaL_checktype(L, narg, LUA_TTABLE); - - check_tablevalue(L, "x", narg, &vp->x, false); - check_tablevalue(L, "y", narg, &vp->y, false); - check_tablevalue(L, "width", narg, &vp->width, false); - check_tablevalue(L, "height", narg, &vp->height, false); -#ifdef HAVE_LCD_BITMAP - check_tablevalue(L, "font", narg, &vp->font, false); - check_tablevalue(L, "drawmode", narg, &vp->drawmode, false); -#endif -#if LCD_DEPTH > 1 - check_tablevalue(L, "fg_pattern", narg, &vp->fg_pattern, true); - check_tablevalue(L, "bg_pattern", narg, &vp->bg_pattern, true); -#endif - - return vp; -} - -RB_WRAP(set_viewport) -{ - static struct viewport vp; - int screen = luaL_optint(L, 2, SCREEN_MAIN); - rb->screens[screen]->set_viewport(opt_viewport(L, 1, &vp, NULL)); - return 0; -} - -RB_WRAP(clear_viewport) -{ - int screen = luaL_optint(L, 1, SCREEN_MAIN); - rb->screens[screen]->clear_viewport(); - return 0; -} - RB_WRAP(current_tick) { lua_pushinteger(L, *rb->current_tick); @@ -172,25 +112,6 @@ RB_WRAP(touchscreen_get_mode) } #endif -RB_WRAP(font_getstringsize) -{ - const unsigned char* str = luaL_checkstring(L, 1); - int fontnumber = luaL_checkint(L, 2); - int w, h; - - if (fontnumber == FONT_UI) - fontnumber = rb->global_status->font_id[SCREEN_MAIN]; - else - fontnumber = FONT_SYSFIXED; - - int result = rb->font_getstringsize(str, &w, &h, fontnumber); - lua_pushinteger(L, result); - lua_pushinteger(L, w); - lua_pushinteger(L, h); - - return 3; -} - RB_WRAP(current_path) { return get_current_path(L, 1); @@ -507,9 +428,6 @@ static const luaL_Reg rocklib[] = RB_FUNC(kbd_input), - RB_FUNC(font_getstringsize), - RB_FUNC(set_viewport), - RB_FUNC(clear_viewport), RB_FUNC(current_path), RB_FUNC(gui_syncyesno_run), RB_FUNC(do_menu), @@ -563,6 +481,11 @@ LUALIB_API int luaopen_rock(lua_State *L) RB_CONSTANT(LCD_DEPTH), RB_CONSTANT(LCD_HEIGHT), RB_CONSTANT(LCD_WIDTH), +#ifdef HAVE_REMOTE_LCD + RB_CONSTANT(LCD_REMOTE_DEPTH), + RB_CONSTANT(LCD_REMOTE_HEIGHT), + RB_CONSTANT(LCD_REMOTE_WIDTH), +#endif RB_CONSTANT(FONT_SYSFIXED), RB_CONSTANT(FONT_UI), diff --git a/apps/plugins/lua/rocklib_aux.pl b/apps/plugins/lua/rocklib_aux.pl index 5114e7b6f7..8ad59317d6 100755 --- a/apps/plugins/lua/rocklib_aux.pl +++ b/apps/plugins/lua/rocklib_aux.pl @@ -73,6 +73,14 @@ my @forbidden_functions = ('^open$', '^codec_', '^timer_', '^lcd_(mono_)?+bitmap', + '^lcd_(draw|fill|update_)rect$', + '^lcd_draw(line|pixel)$', + '^lcd_(h|v)line$', + '^lcd_(update|clear_display|set_drawmode)$', + '^lcd_setfont$', + '^lcd_(set|get)_(fore|back)ground$', + '^lcd_put(s|sxy|s_scroll)$', + '^lcd_scroll_stop$', '^__.+$', '^.+_(un)?cached$', '^audio_.+$', diff --git a/apps/plugins/lua/rocklib_img.c b/apps/plugins/lua/rocklib_img.c index 6cece9c836..9d9fb120f8 100644 --- a/apps/plugins/lua/rocklib_img.c +++ b/apps/plugins/lua/rocklib_img.c @@ -1217,21 +1217,180 @@ static const struct luaL_reg rli_lib [] = */ #define RB_WRAP(func) static int rock_##func(lua_State UNUSED_ATTR *L) + +#if defined NB_SCREENS && (NB_SCREENS > 1) +#define RB_SCREENS(luastate, narg, func, ...) \ + rb->screens[get_screen(luastate, narg)]->func(__VA_ARGS__) + +static int get_screen(lua_State *L, int narg) +{ + int screen = luaL_optint(L, narg, SCREEN_MAIN); + + if(screen < SCREEN_MAIN) + screen = SCREEN_MAIN; + else if(screen > NB_SCREENS) + screen = NB_SCREENS; + + return screen; +} +#else /* only SCREEN_MAIN exists */ +#define RB_SCREENS(luastate, narg, func, ...) \ + rb->screens[SCREEN_MAIN]->func(__VA_ARGS__) +#endif + +RB_WRAP(lcd_update) +{ + RB_SCREENS(L, 1, update); + return 0; +} + +RB_WRAP(lcd_clear_display) +{ + RB_SCREENS(L, 1, clear_display); + return 0; +} + +RB_WRAP(lcd_set_drawmode) +{ + int mode = (int) luaL_checkint(L, 1); + RB_SCREENS(L, 2, set_drawmode, mode); + return 0; +} + +/* helper function for lcd_puts functions */ +static const unsigned char * lcd_putshelper(lua_State *L, int *x, int *y) +{ + *x = (int) luaL_checkint(L, 1); + *y = (int) luaL_checkint(L, 2); + return luaL_checkstring(L, 3); +} + +RB_WRAP(lcd_putsxy) +{ + int x, y; + const unsigned char *string = lcd_putshelper(L, &x, &y); + RB_SCREENS(L, 4, putsxy, x, y, string); + return 0; +} + +RB_WRAP(lcd_puts) +{ + int x, y; + const unsigned char * string = lcd_putshelper(L, &x, &y); + RB_SCREENS(L, 4, puts, x, y, string); + return 0; +} + +RB_WRAP(lcd_puts_scroll) +{ + int x, y; + const unsigned char * string = lcd_putshelper(L, &x, &y); + bool result = RB_SCREENS(L, 4, puts_scroll, x, y, string); + lua_pushboolean(L, result); + return 1; +} + +RB_WRAP(lcd_scroll_stop) +{ + RB_SCREENS(L, 1, scroll_stop); + return 0; +} + +/* Helper function for opt_viewport */ +static int check_tablevalue(lua_State *L, const char* key, int tablepos) +{ + lua_getfield(L, tablepos, key); /* Find table[key] */ + + int val = lua_tointeger(L, -1); + + lua_pop(L, 1); /* Pop the value off the stack */ + return val; +} + +static inline struct viewport* opt_viewport(lua_State *L, + int narg, + struct viewport* vp, + struct viewport* alt) +{ + if(lua_isnoneornil(L, narg)) + return alt; + + luaL_checktype(L, narg, LUA_TTABLE); + + vp->x = check_tablevalue(L, "x", narg); + vp->y = check_tablevalue(L, "y", narg); + vp->width = check_tablevalue(L, "width", narg); + vp->height = check_tablevalue(L, "height", narg); #ifdef HAVE_LCD_BITMAP + vp->font = check_tablevalue(L, "font", narg); + vp->drawmode = check_tablevalue(L, "drawmode", narg); +#endif +#if LCD_DEPTH > 1 + vp->fg_pattern = (unsigned int) check_tablevalue(L, "fg_pattern", narg); + vp->bg_pattern = (unsigned int) check_tablevalue(L, "bg_pattern", narg); +#endif + + return vp; +} + +RB_WRAP(set_viewport) +{ + static struct viewport vp; + RB_SCREENS(L, 2, set_viewport, opt_viewport(L, 1, &vp, NULL)); + return 0; +} + +RB_WRAP(clear_viewport) +{ + RB_SCREENS(L, 1, clear_viewport); + return 0; +} + +RB_WRAP(font_getstringsize) +{ + const unsigned char* str = luaL_checkstring(L, 1); + int fontnumber = lua_tointeger(L, 2); + int w, h, result; + + if (fontnumber == FONT_UI) + fontnumber = rb->global_status->font_id[SCREEN_MAIN]; + else + fontnumber = FONT_SYSFIXED; + + if lua_isnil(L, 2) + result = RB_SCREENS(L, 3, getstringsize, str, &w, &h); + else + result = rb->font_getstringsize(str, &w, &h, fontnumber); + + lua_pushinteger(L, result); + lua_pushinteger(L, w); + lua_pushinteger(L, h); + + return 3; +} + +#ifdef HAVE_LCD_BITMAP + RB_WRAP(lcd_framebuffer) { rli_wrap(L, rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT); return 1; } -/* helper function for lcd_xxx_bitmap functions */ -static int get_bmp_bounds(lua_State *L, int npos, int *x, int *y, int *w, int* h) +RB_WRAP(lcd_setfont) +{ + int font = (int) luaL_checkint(L, 1); + RB_SCREENS(L, 2, setfont, font); + return 0; +} + +/* helper function for lcd_xxx_bitmap/rect functions */ +static void get_rect_bounds(lua_State *L, int narg, int *x, int *y, int *w, int* h) { - *x = luaL_checkint(L, npos); - *y = luaL_checkint(L, npos + 1); - *w = luaL_checkint(L, npos + 2); - *h = luaL_checkint(L, npos + 3); - return luaL_optint(L, npos + 4, SCREEN_MAIN); + *x = luaL_checkint(L, narg); + *y = luaL_checkint(L, narg + 1); + *w = luaL_checkint(L, narg + 2); + *h = luaL_checkint(L, narg + 3); } RB_WRAP(lcd_mono_bitmap_part) @@ -1241,9 +1400,10 @@ RB_WRAP(lcd_mono_bitmap_part) int src_y = luaL_checkint(L, 3); int stride = luaL_checkint(L, 4); int x, y, width, height; - int screen = get_bmp_bounds(L, 5, &x, &y, &width, &height); + get_rect_bounds(L, 5, &x, &y, &width, &height); - rb->screens[screen]->mono_bitmap_part((const unsigned char *)src->data, src_x, src_y, stride, x, y, width, height); + RB_SCREENS(L, 9, mono_bitmap_part, (const unsigned char *)src->data, + src_x, src_y, stride, x, y, width, height); return 0; } @@ -1251,9 +1411,9 @@ RB_WRAP(lcd_mono_bitmap) { struct rocklua_image *src = rli_checktype(L, 1); int x, y, width, height; - int screen = get_bmp_bounds(L, 2, &x, &y, &width, &height); + get_rect_bounds(L, 2, &x, &y, &width, &height); - rb->screens[screen]->mono_bitmap((const unsigned char *)src->data, x, y, width, height); + RB_SCREENS(L, 6, mono_bitmap, (const unsigned char *)src->data, x, y, width, height); return 0; } @@ -1265,9 +1425,9 @@ RB_WRAP(lcd_bitmap_part) int src_y = luaL_checkint(L, 3); int stride = luaL_checkint(L, 4); int x, y, width, height; - int screen = get_bmp_bounds(L, 5, &x, &y, &width, &height); + get_rect_bounds(L, 5, &x, &y, &width, &height); - rb->screens[screen]->bitmap_part(src->data, src_x, src_y, stride, x, y, width, height); + RB_SCREENS(L, 9, bitmap_part, src->data, src_x, src_y, stride, x, y, width, height); return 0; } @@ -1275,9 +1435,9 @@ RB_WRAP(lcd_bitmap) { struct rocklua_image *src = rli_checktype(L, 1); int x, y, width, height; - int screen = get_bmp_bounds(L, 2, &x, &y, &width, &height); + get_rect_bounds(L, 2, &x, &y, &width, &height); - rb->screens[screen]->bitmap(src->data, x, y, width, height); + RB_SCREENS(L, 6, bitmap, src->data, x, y, width, height); return 0; } @@ -1291,6 +1451,35 @@ RB_WRAP(lcd_get_backdrop) return 1; } + +RB_WRAP(lcd_set_foreground) +{ + unsigned foreground = (unsigned) luaL_checkint(L, 1); + RB_SCREENS(L, 2, set_foreground, foreground); + return 0; +} + +RB_WRAP(lcd_get_foreground) +{ + unsigned result = RB_SCREENS(L, 1, get_foreground); + lua_pushinteger(L, result); + return 1; +} + +RB_WRAP(lcd_set_background) +{ + unsigned background = (unsigned) luaL_checkint(L, 1); + RB_SCREENS(L, 2, set_background, background); + return 0; +} + +RB_WRAP(lcd_get_background) +{ + unsigned result = RB_SCREENS(L, 1, get_background); + lua_pushinteger(L, result); + return 1; +} + #endif /* LCD_DEPTH > 1 */ #if LCD_DEPTH == 16 @@ -1301,9 +1490,10 @@ RB_WRAP(lcd_bitmap_transparent_part) int src_y = luaL_checkint(L, 3); int stride = luaL_checkint(L, 4); int x, y, width, height; - int screen = get_bmp_bounds(L, 5, &x, &y, &width, &height); + get_rect_bounds(L, 5, &x, &y, &width, &height); - rb->screens[screen]->transparent_bitmap_part(src->data, src_x, src_y, stride, x, y, width, height); + RB_SCREENS(L, 9, transparent_bitmap_part, src->data, src_x, + src_y, stride, x, y, width, height); return 0; } @@ -1311,13 +1501,71 @@ RB_WRAP(lcd_bitmap_transparent) { struct rocklua_image *src = rli_checktype(L, 1); int x, y, width, height; - int screen = get_bmp_bounds(L, 2, &x, &y, &width, &height); + get_rect_bounds(L, 2, &x, &y, &width, &height); - rb->screens[screen]->transparent_bitmap(src->data, x, y, width, height); + RB_SCREENS(L, 6, transparent_bitmap, src->data, x, y, width, height); return 0; } #endif /* LCD_DEPTH == 16 */ +RB_WRAP(lcd_update_rect) +{ + int x, y, width, height; + get_rect_bounds(L, 1, &x, &y, &width, &height); + RB_SCREENS(L, 5, update_rect, x, y, width, height); + return 0; +} + +RB_WRAP(lcd_drawrect) +{ + int x, y, width, height; + get_rect_bounds(L, 1, &x, &y, &width, &height); + RB_SCREENS(L, 5, drawrect, x, y, width, height); + return 0; +} + +RB_WRAP(lcd_fillrect) +{ + int x, y, width, height; + get_rect_bounds(L, 1, &x, &y, &width, &height); + RB_SCREENS(L, 5, fillrect, x, y, width, height); + return 0; +} + +RB_WRAP(lcd_drawline) +{ + int x1, y1, x2, y2; + get_rect_bounds(L, 1, &x1, &y1, &x2, &y2); + RB_SCREENS(L, 5, drawline, x1, y1, x2, y2); + return 0; +} + +RB_WRAP(lcd_hline) +{ + int x1 = (int) luaL_checkint(L, 1); + int x2 = (int) luaL_checkint(L, 2); + int y = (int) luaL_checkint(L, 3); + RB_SCREENS(L, 4, hline, x1, x2, y); + return 0; +} + +RB_WRAP(lcd_vline) +{ + int x = (int) luaL_checkint(L, 1); + int y1 = (int) luaL_checkint(L, 2); + int y2 = (int) luaL_checkint(L, 3); + RB_SCREENS(L, 4, vline, x, y1, y2); + return 0; +} + +RB_WRAP(lcd_drawpixel) +{ + int x = (int) luaL_checkint(L, 1); + int y = (int) luaL_checkint(L, 2); + RB_SCREENS(L, 3, drawpixel, x, y); + return 0; +} + #endif /* defined(LCD_BITMAP) */ #ifdef HAVE_LCD_COLOR @@ -1377,19 +1625,42 @@ RB_WRAP(read_bmp_file) static const luaL_Reg rocklib_img[] = { /* Graphics */ + R(lcd_update), + R(lcd_clear_display), + R(lcd_set_drawmode), + R(lcd_putsxy), + R(lcd_puts), + R(lcd_puts_scroll), + R(lcd_scroll_stop), + R(set_viewport), + R(clear_viewport), + R(font_getstringsize), #ifdef HAVE_LCD_BITMAP R(lcd_framebuffer), + R(lcd_setfont), R(lcd_mono_bitmap_part), R(lcd_mono_bitmap), #if LCD_DEPTH > 1 R(lcd_get_backdrop), R(lcd_bitmap_part), R(lcd_bitmap), + R(lcd_set_foreground), + R(lcd_get_foreground), + R(lcd_set_background), + R(lcd_get_background), #endif #if LCD_DEPTH == 16 R(lcd_bitmap_transparent_part), R(lcd_bitmap_transparent), #endif + R(lcd_update_rect), + R(lcd_drawrect), + R(lcd_fillrect), + R(lcd_drawline), + R(lcd_hline), + R(lcd_vline), + R(lcd_drawpixel), + #endif /*HAVE_LCD_BITMAP*/ #ifdef HAVE_LCD_COLOR R(lcd_rgbpack), -- cgit v1.2.3