diff --git a/configure.ac b/configure.ac index 2e7c6d353..1863e8f80 100644 --- a/configure.ac +++ b/configure.ac @@ -233,6 +233,13 @@ if test "$enable_testing" = "yes"; then AC_DEFINE(ENABLE_TESTING,1,[include devel code parts for neutrino tests - not recommended for general users!]) fi +AC_ARG_ENABLE([fribidi], + AS_HELP_STRING([--enable-fribidi], [enable fribidi support]) +) +AM_CONDITIONAL(ENABLE_FRIBIDI, test "$enable_fribidi" = "yes") +AS_IF([test "$enable_fribidi" = "yes"], + AC_DEFINE(ENABLE_FRIBIDI, 1, [enable fribidi support]) +) if test "$BOXTYPE" = "coolstream"; then if test -e ${srcdir}/lib/hardware/coolstream/hd1/libcoolstream/nevis_ir.h; then diff --git a/src/Makefile.am b/src/Makefile.am index 616e49b8f..f33f8f87c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -132,6 +132,11 @@ neutrino_LDADD += -lgif else neutrino_LDADD += -lungif endif + +if ENABLE_FRIBIDI +neutrino_LDADD += -lfribidi +endif + if ENABLE_LUA neutrino_LDADD += @LUA_LIBS@ endif diff --git a/src/driver/fontrenderer.cpp b/src/driver/fontrenderer.cpp index 5d4ee16b7..375be1570 100644 --- a/src/driver/fontrenderer.cpp +++ b/src/driver/fontrenderer.cpp @@ -39,6 +39,10 @@ #include #include +#ifdef ENABLE_FRIBIDI +#include +#endif + FT_Error FBFontRenderClass::myFTC_Face_Requester(FTC_FaceID face_id, FT_Library /*library*/, FT_Pointer request_data, @@ -388,6 +392,49 @@ int UTF8ToUnicode(const char * &text, const bool utf8_encoded) // returns -1 on return unicode_value; } +#ifdef ENABLE_FRIBIDI +static std::string fribidi_shape_char(const char * text) +{ + if(text && *text) + { + int len = strlen(text); + char * rtl_text = NULL; + int rtl_len = 0; + + fribidi_set_mirroring(true); + fribidi_set_reorder_nsm(false); + + // init to utf-8 + FriBidiCharSet fribidi_charset = FRIBIDI_CHAR_SET_UTF8; + + // tell bidi that we need bidirectional + FriBidiCharType fribidi_chartype = FRIBIDI_TYPE_L; + + // our buffer + FriBidiChar *logical = (FriBidiChar *)alloca(sizeof(FriBidiChar)*(len + 1)); + FriBidiChar *visual = (FriBidiChar *)alloca(sizeof(FriBidiChar)*(len + 1)); + + // convert from the selected charset to Unicode + rtl_len = fribidi_charset_to_unicode(fribidi_charset, const_cast(text), len, logical); + //printf("len: %d rtl_len: %d\n", len, rtl_len); + + // logical to visual + if (fribidi_log2vis(logical, rtl_len, &fribidi_chartype, visual, NULL, NULL, NULL)) + { + // removes bidirectional marks + fribidi_remove_bidi_marks(visual, rtl_len, NULL, NULL, NULL); + + rtl_text = (char *)alloca(sizeof(char)*(rtl_len * 4 + 1)); + fribidi_unicode_to_charset(fribidi_charset, visual, rtl_len, rtl_text); + + return std::string(rtl_text); + } + } + + return std::string(text); +} +#endif + void Font::paintFontPixel(fb_pixel_t *td, uint8_t src) { #define DST_BLUE 0x80 @@ -448,6 +495,11 @@ void Font::RenderString(int x, int y, const int width, const char *text, const f pthread_mutex_lock( &renderer->render_mutex ); +#ifdef ENABLE_FRIBIDI + std::string Text = fribidi_shape_char(text); + text = Text.c_str(); +#endif + FT_Error err = FTC_Manager_LookupSize(renderer->cacheManager, &scaler, &size); if (err != 0) { @@ -638,6 +690,11 @@ int Font::getRenderWidth(const char *text, const bool utf8_encoded) { pthread_mutex_lock( &renderer->render_mutex ); +#ifdef ENABLE_FRIBIDI + std::string Text = fribidi_shape_char(text); + text = Text.c_str(); +#endif + FT_Error err = FTC_Manager_LookupSize(renderer->cacheManager, &scaler, &size); if (err != 0) { diff --git a/src/gui/lua/Makefile.am b/src/gui/lua/Makefile.am index 69d439249..2e8165ce1 100644 --- a/src/gui/lua/Makefile.am +++ b/src/gui/lua/Makefile.am @@ -37,6 +37,7 @@ libneutrino_gui_lua_a_SOURCES = \ lua_menue.cpp \ lua_messagebox.cpp \ lua_misc.cpp \ + lua_progresswindow.cpp \ lua_stringinput.cpp \ lua_threads.cpp \ lua_threads_copy.cpp \ diff --git a/src/gui/lua/lua_api_version.h b/src/gui/lua/lua_api_version.h index 55b19f4e0..9e8343ca1 100644 --- a/src/gui/lua/lua_api_version.h +++ b/src/gui/lua/lua_api_version.h @@ -4,4 +4,4 @@ * to luainstance.h changes */ #define LUA_API_VERSION_MAJOR 1 -#define LUA_API_VERSION_MINOR 70 +#define LUA_API_VERSION_MINOR 72 diff --git a/src/gui/lua/lua_cc_window.cpp b/src/gui/lua/lua_cc_window.cpp index 2225797bc..819fe18d2 100644 --- a/src/gui/lua/lua_cc_window.cpp +++ b/src/gui/lua/lua_cc_window.cpp @@ -220,7 +220,10 @@ int CLuaInstCCWindow::CCWindowSetCaption(lua_State *L) std::string name = ""; tableLookup(L, "name", name) || tableLookup(L, "title", name) || tableLookup(L, "caption", name); - D->w->setWindowCaption(name); + lua_Integer alignment = (lua_Integer)CTextBox::NO_AUTO_LINEBREAK; + tableLookup(L, "alignment", alignment); + + D->w->setWindowCaption(name, alignment | (lua_Integer)CTextBox::NO_AUTO_LINEBREAK); return 0; } diff --git a/src/gui/lua/lua_progresswindow.cpp b/src/gui/lua/lua_progresswindow.cpp new file mode 100644 index 000000000..c6bc45d01 --- /dev/null +++ b/src/gui/lua/lua_progresswindow.cpp @@ -0,0 +1,175 @@ +/* + * lua progress window + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "luainstance.h" +#include "lua_progresswindow.h" + +CLuaInstProgressWindow* CLuaInstProgressWindow::getInstance() +{ + static CLuaInstProgressWindow* LuaInstProgressWindow = NULL; + + if(!LuaInstProgressWindow) + LuaInstProgressWindow = new CLuaInstProgressWindow(); + return LuaInstProgressWindow; +} + +void CLuaInstProgressWindow::ProgressWindowRegister(lua_State *L) +{ + luaL_Reg meth[] = { + { "new", CLuaInstProgressWindow::CProgressWindowNew }, + { "paint", CLuaInstProgressWindow::CProgressWindowPaint }, + { "hide", CLuaInstProgressWindow::CProgressWindowHide }, + { "showStatus", CLuaInstProgressWindow::CProgressWindowShowLocalStatus}, + { "showLocalStatus", CLuaInstProgressWindow::CProgressWindowShowLocalStatus}, + { "showGlobalStatus",CLuaInstProgressWindow::CProgressWindowShowGlobalStatus }, + { "setTitle", CLuaInstProgressWindow::CProgressWindowSetTitle}, + { "__gc", CLuaInstProgressWindow::CProgressWindowDelete }, + { NULL, NULL } + }; + + luaL_newmetatable(L, "cprogresswindow"); + luaL_setfuncs(L, meth, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -1, "__index"); + lua_setglobal(L, "cprogresswindow"); +} + + +int CLuaInstProgressWindow::CProgressWindowNew(lua_State *L) +{ + lua_assert(lua_istable(L,1)); + + std::string name = ""; + tableLookup(L, "name", name) || tableLookup(L, "title", name) || tableLookup(L, "caption", name); + + CLuaCProgressWindow **udata = (CLuaCProgressWindow **) lua_newuserdata(L, sizeof(CLuaCProgressWindow *)); + *udata = new CLuaCProgressWindow(); + +#if 0 + /* Enable when pu/fb-setmode branch is merged in master */ + (*udata)->w = new CProgressWindow(name); +#else + (*udata)->w = new CProgressWindow(); + (*udata)->w->setTitle(name); +#endif + + luaL_getmetatable(L, "cprogresswindow"); + lua_setmetatable(L, -2); + return 1; +} + +CLuaCProgressWindow *CLuaInstProgressWindow::CProgressWindowCheck(lua_State *L, int n) +{ + return *(CLuaCProgressWindow **) luaL_checkudata(L, n, "cprogresswindow"); +} + +int CLuaInstProgressWindow::CProgressWindowPaint(lua_State *L) +{ + lua_assert(lua_istable(L,1)); + CLuaCProgressWindow *D = CProgressWindowCheck(L, 1); + if (!D) return 0; + + bool do_save_bg = true; + if (!tableLookup(L, "do_save_bg", do_save_bg)) { + std::string tmp = "true"; + if (tableLookup(L, "do_save_bg", tmp)) + paramBoolDeprecated(L, tmp.c_str()); + do_save_bg = (tmp == "true" || tmp == "1" || tmp == "yes"); + } + D->w->paint(do_save_bg); + return 0; +} + +int CLuaInstProgressWindow::CProgressWindowHide(lua_State *L) +{ + lua_assert(lua_istable(L,1)); + CLuaCProgressWindow *D = CProgressWindowCheck(L, 1); + if (!D) return 0; + + bool tmp1 = false; + std::string tmp2 = "false"; + if ((tableLookup(L, "no_restore", tmp1)) || (tableLookup(L, "no_restore", tmp2))) + obsoleteHideParameter(L); + + D->w->hide(); + return 0; +} + +int CLuaInstProgressWindow::CProgressWindowSetTitle(lua_State *L) +{ + lua_assert(lua_istable(L,1)); + CLuaCProgressWindow *D = CProgressWindowCheck(L, 1); + if (!D) return 0; + + std::string name = ""; + tableLookup(L, "name", name) || tableLookup(L, "title", name) || tableLookup(L, "caption", name); + + D->w->setTitle(name); + return 0; +} + +int CLuaInstProgressWindow::CProgressWindowShowStatusInternal(lua_State *L, bool local) +{ + lua_assert(lua_istable(L,1)); + CLuaCProgressWindow *D = CProgressWindowCheck(L, 1); + if (!D) return 0; + + lua_Unsigned prog; + std::string statusText = std::string(); + lua_Integer max = 100 ; + + tableLookup(L, "prog", prog); + tableLookup(L, "statusText", statusText); + tableLookup(L, "max", max); + + if (local) + D->w->showLocalStatus(prog, max, statusText); + else + D->w->showGlobalStatus(prog, max, statusText); + + return 0; +} + +int CLuaInstProgressWindow::CProgressWindowShowLocalStatus(lua_State *L) +{ + return CProgressWindowShowStatusInternal(L, true); +} + +int CLuaInstProgressWindow::CProgressWindowShowGlobalStatus(lua_State *L) +{ + return CProgressWindowShowStatusInternal(L, false); +} + +int CLuaInstProgressWindow::CProgressWindowDelete(lua_State *L) +{ + LUA_DEBUG("CLuaInstProgressWindow::%s %d\n", __func__, lua_gettop(L)); + CLuaCProgressWindow *D = CProgressWindowCheck(L, 1); + if (!D) return 0; + delete D; + return 0; +} diff --git a/src/gui/lua/lua_progresswindow.h b/src/gui/lua/lua_progresswindow.h new file mode 100644 index 000000000..f1701a97e --- /dev/null +++ b/src/gui/lua/lua_progresswindow.h @@ -0,0 +1,49 @@ +/* + * lua progress window + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _LUAPROGRESSWINDOW_H_ +#define _LUAPROGRESSWINDOW_H_ + +class CLuaCProgressWindow +{ + public: + CProgressWindow *w; + CLuaCProgressWindow() { w = NULL; } + ~CLuaCProgressWindow() { delete w; } +}; + +class CLuaInstProgressWindow +{ + public: + CLuaInstProgressWindow() {}; + ~CLuaInstProgressWindow() {}; + static CLuaInstProgressWindow* getInstance(); + static void ProgressWindowRegister(lua_State *L); + + private: + static int CProgressWindowNew(lua_State *L); + static CLuaCProgressWindow *CProgressWindowCheck(lua_State *L, int n); + static int CProgressWindowPaint(lua_State *L); + static int CProgressWindowHide(lua_State *L); + static int CProgressWindowSetTitle(lua_State *L); + static int CProgressWindowDelete(lua_State *L); + static int CProgressWindowShowStatusInternal(lua_State *L, bool local); + static int CProgressWindowShowLocalStatus(lua_State *L); + static int CProgressWindowShowGlobalStatus(lua_State *L); +}; + +#endif //_LUAPROGRESSWINDOW_H_ diff --git a/src/gui/lua/luainstance.cpp b/src/gui/lua/luainstance.cpp index 9adfa1d4e..ee304db0a 100644 --- a/src/gui/lua/luainstance.cpp +++ b/src/gui/lua/luainstance.cpp @@ -51,6 +51,7 @@ #include "lua_menue.h" #include "lua_messagebox.h" #include "lua_misc.h" +#include "lua_progresswindow.h" #include "lua_stringinput.h" #include "lua_threads.h" #include "lua_video.h" @@ -383,22 +384,35 @@ static void set_lua_variables(lua_State *L) { NULL, 0 } }; + /* + * possible text allignment modes usable for window header caption + * API: >= v1.71 + */ + table_key text_alignment[] = + { + { "DEFAULT", (lua_Integer)CTextBox::NO_AUTO_LINEBREAK}, + { "CENTER", (lua_Integer)CTextBox::CENTER}, + { "RIGHT", (lua_Integer)CTextBox::RIGHT}, + { NULL, 0 } + }; + /* list of environment variable arrays to be exported */ lua_envexport e[] = { - { "RC", keyname }, - { "SCREEN", screenopts }, - { "FONT", fontlist }, - { "CORNER", corners }, - { "OFFSET", offsets }, - { "MENU_RETURN", menureturn }, - { "APIVERSION", apiversion }, - { "PLAYSTATE", playstate }, - { "CC", ccomponents }, - { "DYNFONT", dynfont }, - { "CURL", curl_status }, - { "NMODE", neutrino_mode }, - { "POSTMSG", post_msg }, + { "RC", keyname }, + { "SCREEN", screenopts }, + { "FONT", fontlist }, + { "CORNER", corners }, + { "OFFSET", offsets }, + { "MENU_RETURN", menureturn }, + { "APIVERSION", apiversion }, + { "PLAYSTATE", playstate }, + { "CC", ccomponents }, + { "DYNFONT", dynfont }, + { "CURL", curl_status }, + { "NMODE", neutrino_mode }, + { "POSTMSG", post_msg }, + { "TEXT_ALIGNMENT", text_alignment }, { NULL, NULL } }; @@ -660,6 +674,8 @@ void LuaInstRegisterFunctions(lua_State *L, bool fromThreads/*=false*/) CLuaInstStringInput::getInstance()->StringInputRegister(L); CLuaInstMisc::getInstance()->LuaMiscRegister(L); CLuaInstVideo::getInstance()->LuaVideoRegister(L); + CLuaInstProgressWindow::getInstance()->ProgressWindowRegister(L); + if (!fromThreads) CLLThread::getInstance()->LuaThreadsRegister(L); } diff --git a/src/lcddisplay/fontrenderer.cpp b/src/lcddisplay/fontrenderer.cpp index 43bf2562c..e52e71d6e 100644 --- a/src/lcddisplay/fontrenderer.cpp +++ b/src/lcddisplay/fontrenderer.cpp @@ -35,6 +35,10 @@ #include #include FT_FREETYPE_H +#ifdef ENABLE_FRIBIDI +#include +#endif + FT_Error LcdFontRenderClass::myFTC_Face_Requester(FTC_FaceID face_id, FT_Library /*library*/, FT_Pointer request_data, @@ -230,11 +234,20 @@ extern int UTF8ToUnicode(const char * &text, const bool utf8_encoded); // return } #endif +#ifdef ENABLE_FRIBIDI +std::string fribidi_shape_char(const char * text); +#endif + void LcdFont::RenderString(int x, int y, const int width, const char * text, const int color, const int selected, const bool utf8_encoded) { int err; pthread_mutex_lock(&renderer->render_mutex); +#ifdef ENABLE_FRIBIDI + std::string Text = fribidi_shape_char(text); + text = Text.c_str(); +#endif + FTC_ScalerRec scaler; scaler.face_id = font.face_id; @@ -311,6 +324,12 @@ void LcdFont::RenderString(int x, int y, const int width, const char * text, con int LcdFont::getRenderWidth(const char * text, const bool utf8_encoded) { pthread_mutex_lock(&renderer->render_mutex); + +#ifdef ENABLE_FRIBIDI + std::string Text = fribidi_shape_char(text); + text = Text.c_str(); +#endif + FT_Error err; FTC_ScalerRec scaler; scaler.face_id = font.face_id;