From a307e806eb97ec35c28c57f46f85009f49427d1b Mon Sep 17 00:00:00 2001 From: "M. Liebmann" Date: Fri, 27 Nov 2015 12:11:50 +0100 Subject: [PATCH] CLuaInstance: Add DynFonts for lua scripts - You can create fixed-size fonts for use in Lua Scripts - The fonts are deleted after the script - The use of fonts is limited to the following functions currently: - RenderString() - getRenderWidth() - FontHeight() - Example in Lua scripts: Normal usage: local font = FONT.MENU RenderString(font, ....) Use DynFonts: Creates a font with height of 50px: local font = n:getDynFont(0, 50) local useDynFont = true RenderString(useDynFont, font, ....) or Creates a font in which the text("Example: xyz") has a width of 200px: local font = n:getDynFont(200, 0, "Example: xyz") local useDynFont = true RenderString(useDynFont, font, ....) - Set Lua api version to 1.13 --- src/gui/luainstance.cpp | 220 ++++++++++++++++++++++++++++++++++------ src/gui/luainstance.h | 15 ++- 2 files changed, 205 insertions(+), 30 deletions(-) diff --git a/src/gui/luainstance.cpp b/src/gui/luainstance.cpp index e27bf7e12..a6d0ef62c 100644 --- a/src/gui/luainstance.cpp +++ b/src/gui/luainstance.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -310,6 +311,18 @@ static void set_lua_variables(lua_State *L) { NULL, 0 } }; + table_key dynfont[] = + { + { "STYLE_REGULAR", (lua_Integer)CNeutrinoFonts::FONT_STYLE_REGULAR }, + { "STYLE_BOLD", (lua_Integer)CNeutrinoFonts::FONT_STYLE_BOLD }, + { "STYLE_ITALIC", (lua_Integer)CNeutrinoFonts::FONT_STYLE_ITALIC }, + { "MAX", (lua_Integer)CNeutrinoFonts::DYNFONTEXT_MAX }, + { "MAXIMUM_FONTS", (lua_Integer)CLuaInstance::DYNFONT_MAXIMUM_FONTS }, + { "TO_WIDE", (lua_Integer)CLuaInstance::DYNFONT_TO_WIDE }, + { "TOO_HIGH", (lua_Integer)CLuaInstance::DYNFONT_TOO_HIGH }, + { NULL, 0 } + }; + /* list of environment variable arrays to be exported */ lua_envexport e[] = { @@ -321,6 +334,7 @@ static void set_lua_variables(lua_State *L) { "APIVERSION", apiversion }, { "PLAYSTATE", playstate }, { "CC", ccomponents }, + { "DYNFONT", dynfont }, { NULL, NULL } }; @@ -564,6 +578,7 @@ const luaL_Reg CLuaInstance::methods[] = { "checkVersion", CLuaInstance::checkVersion }, { "createChannelIDfromUrl", CLuaInstance::createChannelIDfromUrl }, { "enableInfoClock", CLuaInstance::enableInfoClock }, + { "getDynFont", CLuaInstance::getDynFont }, { NULL, NULL } }; @@ -671,12 +686,14 @@ int CLuaInstance::PaintBox(lua_State *L) y = luaL_checkint(L, 3); w = luaL_checkint(L, 4); h = luaL_checkint(L, 5); + #if HAVE_COOL_HARDWARE c = luaL_checkunsigned(L, 6); #else /* luaL_checkint does not like e.g. 0xffcc0000 on powerpc (returns INT_MAX) instead */ c = (unsigned int)luaL_checknumber(L, 6); #endif + if (count > 6) radius = luaL_checkint(L, 7); if (count > 7) @@ -872,7 +889,8 @@ int CLuaInstance::GetSize(lua_State *L) int CLuaInstance::RenderString(lua_State *L) { - int x, y, w, boxh, f, center; + int x, y, w, boxh, f, center, id; + Font* font = NULL; unsigned int c; const char *text; int numargs = lua_gettop(L); @@ -884,53 +902,110 @@ int CLuaInstance::RenderString(lua_State *L) CLuaData *W = CheckData(L, 1); if (!W || !W->fbwin) return 0; - f = luaL_checkint(L, 2); /* font number, use FONT_TYPE_XXX in the script */ - text = luaL_checkstring(L, 3); /* text */ - x = luaL_checkint(L, 4); - y = luaL_checkint(L, 5); - if (numargs > 5) + + int step = 0; + bool isDynFont = false; + if (lua_isboolean(L, 2)) { + if (lua_toboolean(L, 2) == true) + isDynFont = true; + step = 1; + } + + if (!isDynFont) { + f = luaL_checkint(L, 2+step); /* font number, use FONT_TYPE_XXX in the script */ + if (f >= SNeutrinoSettings::FONT_TYPE_COUNT || f < 0) + f = SNeutrinoSettings::FONT_TYPE_MENU; + font = g_Font[f]; + } + else { + id = luaL_checkint(L, 2+step); /* dynfont */ + for (fontmap_iterator_t it = W->fontmap.begin(); it != W->fontmap.end(); ++it) { + if (it->first == id) { + font = it->second; + break; + } + } + if (font == NULL) { + printf("[CLuaInstance::%s:%d] no font found\n", __func__, __LINE__); + lua_pushinteger(L, 0); /* no font found */ + return 1; + } + } + + text = luaL_checkstring(L, 3+step); /* text */ + x = luaL_checkint(L, 4+step); + y = luaL_checkint(L, 5+step); + if (numargs > 5+step) #if HAVE_COOL_HARDWARE - c = luaL_checkunsigned(L, 6); + c = luaL_checkunsigned(L, 6+step); #else - c = luaL_checkint(L, 6); + c = luaL_checkint(L, 6+step); #endif - if (numargs > 6) - w = luaL_checkint(L, 7); + if (numargs > 6+step) + w = luaL_checkint(L, 7+step); else w = W->fbwin->dx - x; - if (numargs > 7) - boxh = luaL_checkint(L, 8); - if (numargs > 8) - center = luaL_checkint(L, 9); - if (f >= SNeutrinoSettings::FONT_TYPE_COUNT || f < 0) - f = SNeutrinoSettings::FONT_TYPE_MENU; - int rwidth = g_Font[f]->getRenderWidth(text); + if (numargs > 7+step) + boxh = luaL_checkint(L, 8+step); + if (numargs > 8+step) + center = luaL_checkint(L, 9+step); + + int rwidth = font->getRenderWidth(text); + if (center) { /* center the text inside the box */ if (rwidth < w) x += (w - rwidth) / 2; } checkMagicMask(c); if (boxh > -1) /* if boxh < 0, don't paint string */ - W->fbwin->RenderString(g_Font[f], x, y, w, text, c, boxh); + W->fbwin->RenderString(font, x, y, w, text, c, boxh); lua_pushinteger(L, rwidth); /* return renderwidth */ return 1; } int CLuaInstance::getRenderWidth(lua_State *L) { - int f; + int f, id; + Font* font = NULL; const char *text; DBG1("CLuaInstance::%s %d\n", __func__, lua_gettop(L)); CLuaData *W = CheckData(L, 1); if (!W) return 0; - f = luaL_checkint(L, 2); /* font number, use FONT['xxx'] for FONT_TYPE_xxx in the script */ - text = luaL_checkstring(L, 3); /* text */ - if (f >= SNeutrinoSettings::FONT_TYPE_COUNT || f < 0) - f = SNeutrinoSettings::FONT_TYPE_MENU; - lua_pushinteger(L, (int)g_Font[f]->getRenderWidth(text)); + int step = 0; + bool isDynFont = false; + if (lua_isboolean(L, 2)) { + if (lua_toboolean(L, 2) == true) + isDynFont = true; + step = 1; + } + + if (!isDynFont) { + f = luaL_checkint(L, 2+step); /* font number, use FONT_TYPE_XXX in the script */ + if (f >= SNeutrinoSettings::FONT_TYPE_COUNT || f < 0) + f = SNeutrinoSettings::FONT_TYPE_MENU; + font = g_Font[f]; + } + else { + id = luaL_checkint(L, 2+step); /* dynfont */ + for (fontmap_iterator_t it = W->fontmap.begin(); it != W->fontmap.end(); ++it) { + if (it->first == id) { + font = it->second; + break; + } + } + if (font == NULL) { + printf("[CLuaInstance::%s:%d] no font found\n", __func__, __LINE__); + lua_pushinteger(L, 0); /* no font found */ + return 1; + } + } + + text = luaL_checkstring(L, 3+step); /* text */ + + lua_pushinteger(L, (int)font->getRenderWidth(text)); return 1; } @@ -961,16 +1036,44 @@ int CLuaInstance::GetInput(lua_State *L) int CLuaInstance::FontHeight(lua_State *L) { - int f; + int f, id; + Font* font = NULL; DBG1("CLuaInstance::%s %d\n", __func__, lua_gettop(L)); CLuaData *W = CheckData(L, 1); if (!W) return 0; - f = luaL_checkint(L, 2); /* font number, use FONT['xxx'] for FONT_TYPE_xxx in the script */ - if (f >= SNeutrinoSettings::FONT_TYPE_COUNT || f < 0) - f = SNeutrinoSettings::FONT_TYPE_MENU; - lua_pushinteger(L, (int)g_Font[f]->getHeight()); + + int step = 0; + bool isDynFont = false; + if (lua_isboolean(L, 2)) { + if (lua_toboolean(L, 2) == true) + isDynFont = true; + step = 1; + } + + if (!isDynFont) { + f = luaL_checkint(L, 2+step); /* font number, use FONT_TYPE_XXX in the script */ + if (f >= SNeutrinoSettings::FONT_TYPE_COUNT || f < 0) + f = SNeutrinoSettings::FONT_TYPE_MENU; + font = g_Font[f]; + } + else { + id = luaL_checkint(L, 2+step); /* dynfont */ + for (fontmap_iterator_t it = W->fontmap.begin(); it != W->fontmap.end(); ++it) { + if (it->first == id) { + font = it->second; + break; + } + } + if (font == NULL) { + printf("[CLuaInstance::%s:%d] no font found\n", __func__, __LINE__); + lua_pushinteger(L, 0); /* no font found */ + return 1; + } + } + + lua_pushinteger(L, (int)font->getHeight()); return 1; } @@ -978,6 +1081,12 @@ int CLuaInstance::GCWindow(lua_State *L) { DBG1("CLuaInstance::%s %d\n", __func__, lua_gettop(L)); CLuaData *w = (CLuaData *)lua_unboxpointer(L, 1); + + if (w && w->fbwin) { + w->fontmap.clear(); + } + CNeutrinoFonts::getInstance()->deleteDynFontExtAll(); + delete w->fbwin; w->rcinput = NULL; delete w; @@ -2808,3 +2917,56 @@ int CLuaInstance::enableInfoClock(lua_State *L) } // -------------------------------------------------------------------------------- + +int CLuaInstance::getDynFont(lua_State *L) +{ + int numargs = lua_gettop(L); + CLuaData *W = CheckData(L, 1); + if (!W || !W->fbwin) + return 0; + + if (numargs < 3) { + printf("CLuaInstance::%s: not enough arguments (%d, expected 2)\n", __func__, numargs); + return 0; + } + + lua_Integer fontID = W->fontmap.size(); + if (fontID >= CNeutrinoFonts::DYNFONTEXT_MAX) { + lua_pushnil(L); + lua_pushinteger(L, DYNFONT_MAXIMUM_FONTS); + return 2; + } + + lua_Integer dx = 0, dy = 0, style = CNeutrinoFonts::FONT_STYLE_REGULAR; + std::string text=""; + + dx = luaL_checkint(L, 2); + if (dx > (lua_Integer)CFrameBuffer::getInstance()->getScreenWidth(true)) { + lua_pushnil(L); + lua_pushinteger(L, DYNFONT_TO_WIDE); + return 2; + } + dy = luaL_checkint(L, 3); + if (dy > 100) { + lua_pushnil(L); + lua_pushinteger(L, DYNFONT_TOO_HIGH); + return 2; + } + if (numargs > 3) + text = luaL_checkstring(L, 4); + if (numargs > 4) { + style = luaL_checkint(L, 5); + if (style > CNeutrinoFonts::FONT_STYLE_ITALIC) + style = CNeutrinoFonts::FONT_STYLE_REGULAR; + } + + Font* f = CNeutrinoFonts::getInstance()->getDynFontExt(dx, dy, fontID, text, style); + + lua_Integer id = fontID + 1; + W->fontmap.insert(fontmap_pair_t(id, f)); + lua_pushinteger(L, id); + lua_pushinteger(L, DYNFONT_NO_ERROR); + return 2; +} + +// -------------------------------------------------------------------------------- diff --git a/src/gui/luainstance.h b/src/gui/luainstance.h index 02fd991b5..c0f3b3780 100644 --- a/src/gui/luainstance.h +++ b/src/gui/luainstance.h @@ -34,13 +34,18 @@ extern "C" { #include #define LUA_API_VERSION_MAJOR 1 -#define LUA_API_VERSION_MINOR 12 +#define LUA_API_VERSION_MINOR 13 + +typedef std::pair fontmap_pair_t; +typedef std::map fontmap_t; +typedef fontmap_t::iterator fontmap_iterator_t; /* this is stored as userdata in the lua_State */ struct CLuaData { CFBWindow *fbwin; CRCInput *rcinput; + fontmap_t fontmap; }; struct CLuaMenuItem @@ -200,6 +205,13 @@ public: void runScript(const char *fileName, std::vector *argv = NULL, std::string *result_code = NULL, std::string *result_string = NULL, std::string *error_string = NULL); void abortScript(); + enum { + DYNFONT_NO_ERROR = 0, + DYNFONT_MAXIMUM_FONTS = 1, + DYNFONT_TO_WIDE = 2, + DYNFONT_TOO_HIGH = 3 + }; + // Example: runScript(fileName, "Arg1", "Arg2", "Arg3", ..., NULL); // Type of all parameters: const char* // The last parameter to NULL is imperative. @@ -324,6 +336,7 @@ private: static int checkVersion(lua_State *L); static int createChannelIDfromUrl(lua_State *L); static int enableInfoClock(lua_State *L); + static int getDynFont(lua_State *L); }; #endif /* _LUAINSTANCE_H */