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/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;