diff --git a/mk/cmake/Modules/FindFriBiDi.cmake b/mk/cmake/Modules/FindFriBiDi.cmake new file mode 100644 index 00000000..9fa4e417 --- /dev/null +++ b/mk/cmake/Modules/FindFriBiDi.cmake @@ -0,0 +1,92 @@ +# - Find the native FriBiDI includes and library +# +# +# This module defines +# FRIBIDI_INCLUDE_DIR, where to find fribidi.h, etc. +# FRIBIDI_LIBRARIES, the libraries to link against to use FriBiDi. +# PNG_DEFINITIONS - You should ADD_DEFINITONS(${PNG_DEFINITIONS}) before compiling code that includes png library files. +# FRIBIDI_FOUND, If false, do not try to use PNG. +# also defined, but not for general use are +# FRIBIDI_LIBRARY, where to find the FriBiDi library. +# +# If this module finds an old version of fribidi, then this module will run +# add_definitions(-DOLD_FRIBIDI) + +include(CheckSymbolExists) + +SET(FRIBIDI_FOUND "NO") + +MESSAGE(STATUS "** Searching for library: FriBiDi...") + +# Set variable in temp var, otherwise FIND_PATH might fail +# unset isn't present in the required version of cmake. +FIND_PATH(xFRIBIDI_INCLUDE_DIR fribidi.h + /usr/local/include/fribidi + /usr/include/fribidi + ) +set(FRIBIDI_INCLUDE_DIR ${xFRIBIDI_INCLUDE_DIR}) + +SET(FRIBIDI_NAMES ${FRIBIDI_NAMES} fribidi libfribidi) +FIND_LIBRARY(FRIBIDI_LIBRARY + NAMES ${FRIBIDI_NAMES} + PATHS /usr/lib /usr/local/lib + ) + +IF (FRIBIDI_LIBRARY AND FRIBIDI_INCLUDE_DIR) + SET(CMAKE_REQUIRED_INCLUDES ${FRIBIDI_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${FRIBIDI_LIBRARY}) + CHECK_SYMBOL_EXISTS(fribidi_utf8_to_unicode fribidi.h FOUND_fribidi_utf8_to_unicode) + CHECK_SYMBOL_EXISTS(fribidi_charset_to_unicode fribidi.h FOUND_fribidi_charset_to_unicode) + CHECK_SYMBOL_EXISTS(FRIBIDI_CHAR_SET_UTF8 fribidi.h FOUND_FRIBIDI_CHAR_SET_UTF8) + + # FriBiDi provides both fribidi_utf8_to_unicode and fribidi_charset_to_unicode. + # The difference is that + # 1. fribidi >= 0.10.5 has FRIBIDI_CHAR_SET_UTF8. + # 2. fribidi <= 0.10.4 has FRIBIDI_CHARSET_UTF8. + + # Newer versions of fribidi (not tested the initial version which has the + # issue, but at least 0.19.2 has the issue) no longer have the symbol + # FRIBIDI_CHAR_SET_UTF8. But the symbol is build with some macros confusing + # cmake. To test for that case let the compiler give its verdict. + if(FOUND_fribidi_charset_to_unicode AND NOT FOUND_FRIBIDI_CHAR_SET_UTF8) + file(WRITE "${CMAKE_BINARY_DIR}/fribidi_test.c" + "#include \nint main(){FriBidiCharSet s = FRIBIDI_CHAR_SET_UTF8;}" + ) + try_compile(FOUND_FRIBIDI_CHAR_SET_UTF8 + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/fribidi_test.c" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FRIBIDI_INCLUDE_DIR}" + ) + + file(REMOVE "${CMAKE_BINARY_DIR}/fribidi_test.c") + + endif(FOUND_fribidi_charset_to_unicode AND NOT FOUND_FRIBIDI_CHAR_SET_UTF8) + + if(FOUND_fribidi_charset_to_unicode AND FOUND_FRIBIDI_CHAR_SET_UTF8) + # fribidi >= 0.10.5 + SET(FRIBIDI_LIBRARIES ${FRIBIDI_LIBRARY}) + SET(FRIBIDI_FOUND "YES") + elseif(FOUND_fribidi_utf8_to_unicode) + # fribidi <= 0.10.4 + SET(FRIBIDI_LIBRARIES ${FRIBIDI_LIBRARY}) + SET(FRIBIDI_FOUND "YES") + add_definitions(-DOLD_FRIBIDI) + MESSAGE(STATUS "Legacy FriBiDi: ${FRIBIDI_LIBRARY}") + else() + SET(FRIBIDI_LIBRARIES "NOTFOUND") + SET(FRIBIDI_INCLUDE_DIR "NOTFOUND") + SET(FRIBIDI_FOUND "NO") + endif() +ENDIF (FRIBIDI_LIBRARY AND FRIBIDI_INCLUDE_DIR) + +IF (FRIBIDI_FOUND) + + IF (NOT FRIBIDI_FIND_QUIETLY) + MESSAGE(STATUS "Using FriBiDi: ${FRIBIDI_LIBRARY}") + ENDIF (NOT FRIBIDI_FIND_QUIETLY) +ELSE (FRIBIDI_FOUND) + IF (FRIBIDI_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find FriBiDi library") + ENDIF (FRIBIDI_FIND_REQUIRED) +ENDIF (FRIBIDI_FOUND) + diff --git a/mk/linux/setupBuildDeps.sh b/mk/linux/setupBuildDeps.sh index 208c2c5f..387fa4a7 100755 --- a/mk/linux/setupBuildDeps.sh +++ b/mk/linux/setupBuildDeps.sh @@ -157,7 +157,7 @@ case $distribution in apt-get install build-essential subversion automake autoconf autogen cmake cmake-curses-gui if [ $? != 0 ]; then error_during_installation; exit 1; fi # No libvlc-dev since version (1.1.3) in Debian 6.0/Squeeze is incompatible, no libluajit-5.1-dev because it is not available on Debian 6.0/Squeeze, cf. http://glest.org/glest_board/?topic=8460 - apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libminiupnpc-dev librtmp-dev libgtk2.0-dev + apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libminiupnpc-dev librtmp-dev libgtk2.0-dev libfribidi-dev if [ $? != 0 ]; then error_during_installation; echo '' @@ -166,7 +166,7 @@ case $distribution in fi ;; *) - alternative='apt-get install build-essential subversion automake autoconf autogen cmake cmake-curses-gui; apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libminiupnpc-dev libvlc-dev librtmp-dev libgtk2.0-dev' + alternative='apt-get install build-essential subversion automake autoconf autogen cmake cmake-curses-gui; apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libminiupnpc-dev libvlc-dev librtmp-dev libgtk2.0-dev libfribidi-dev' unsupported_release exit 1 ;; @@ -178,24 +178,24 @@ case $distribution in 8.04) apt-get install build-essential subversion automake autoconf autogen cmake if [ $? != 0 ]; then error_during_installation; exit 1; fi - apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev + apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libfribidi-dev if [ $? != 0 ]; then error_during_installation; exit 1; fi ;; 10.04) apt-get install build-essential subversion automake autoconf autogen cmake if [ $? != 0 ]; then error_during_installation; exit 1; fi - apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew1.5-dev libftgl-dev + apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew1.5-dev libftgl-dev libfribidi-dev if [ $? != 0 ]; then error_during_installation; exit 1; fi ;; 11.10|12.04|12.10) apt-get install build-essential subversion automake autoconf autogen cmake if [ $? != 0 ]; then error_during_installation; exit 1; fi - apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev + apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev libfribidi-dev if [ $? != 0 ]; then error_during_installation; exit 1; fi ;; *) - alternative='apt-get install build-essential subversion automake autoconf autogen cmake; apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev' + alternative='apt-get install build-essential subversion automake autoconf autogen cmake; apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev libfribidi-dev' unsupported_release exit 1 ;; @@ -208,11 +208,11 @@ case $distribution in 13) apt-get install build-essential subversion automake autoconf autogen cmake if [ $? != 0 ]; then error_during_installation; exit 1; fi - apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev + apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev libfribidi-dev if [ $? != 0 ]; then error_during_installation; exit 1; fi ;; *) - alternative='apt-get install build-essential subversion automake autoconf autogen cmake; apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev' + alternative='apt-get install build-essential subversion automake autoconf autogen cmake; apt-get install libsdl1.2-dev libxerces-c2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libvlc-dev libfribidi-dev' unsupported_release exit 1 ;; diff --git a/source/shared_lib/CMakeLists.txt b/source/shared_lib/CMakeLists.txt index 748702e9..b313a7bc 100644 --- a/source/shared_lib/CMakeLists.txt +++ b/source/shared_lib/CMakeLists.txt @@ -17,6 +17,9 @@ IF(BUILD_MEGAGLEST_MODEL_VIEWER OR BUILD_MEGAGLEST_MAP_EDITOR OR BUILD_MEGAGLEST INCLUDE (CheckIncludeFiles) +#Game options +option(ENABLE_FRIBIDI "Enable FriBIDi support" ON) + IF(WIN32) SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} ${PROJECT_SOURCE_DIR}/source/win32_deps/lib @@ -247,6 +250,18 @@ IF(BUILD_MEGAGLEST_MODEL_VIEWER OR BUILD_MEGAGLEST_MAP_EDITOR OR BUILD_MEGAGLEST ENDIF() ENDIF() + + find_package( FriBiDi ) + if(ENABLE_FRIBIDI AND FRIBIDI_LIBRARIES) + add_definitions(-DHAVE_FRIBIDI) + + include_directories( ${FRIBIDI_INCLUDE_DIR} ) + SET(EXTERNAL_LIBS ${EXTERNAL_LIBS} ${FRIBIDI_LIBRARIES}) + + elseif(ENABLE_FRIBIDI AND NOT FRIBIDI_LIBRARIES) + message("Could not find FriBiDi. Disabling FriBiDi support.") + endif() + ######################################################################################### # megaglest lib diff --git a/source/shared_lib/include/graphics/font.h b/source/shared_lib/include/graphics/font.h index 3ee7874a..463ff0cd 100644 --- a/source/shared_lib/include/graphics/font.h +++ b/source/shared_lib/include/graphics/font.h @@ -110,6 +110,8 @@ public: int getSize() const; void setSize(int size); + static void bidi_cvt(string &str_); + static void resetToDefaults(); }; diff --git a/source/shared_lib/sources/graphics/font.cpp b/source/shared_lib/sources/graphics/font.cpp index 73c0a527..094b89c5 100644 --- a/source/shared_lib/sources/graphics/font.cpp +++ b/source/shared_lib/sources/graphics/font.cpp @@ -34,6 +34,11 @@ using namespace Shared::Graphics::Gl; #include "util.h" #include "platform_common.h" #include "platform_util.h" + +#ifdef HAVE_FRIBIDI +#include +#endif + #include "leak_dumper.h" using namespace std; @@ -303,6 +308,39 @@ void Font::setSize(int size) { } } +void Font::bidi_cvt(string &str_) { +#ifdef HAVE_FRIBIDI + char *c_str = const_cast(str_.c_str()); // fribidi forgot const... + FriBidiStrIndex len = str_.length(); + FriBidiChar *bidi_logical = new FriBidiChar[len + 2]; + FriBidiChar *bidi_visual = new FriBidiChar[len + 2]; + char *utf8str = new char[4*len + 1]; //assume worst case here (all 4 Byte characters) + FriBidiCharType base_dir = FRIBIDI_TYPE_ON; + FriBidiStrIndex n; + + +#ifdef OLD_FRIBIDI + n = fribidi_utf8_to_unicode (c_str, len, bidi_logical); +#else + n = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, c_str, len, bidi_logical); +#endif + fribidi_log2vis(bidi_logical, n, &base_dir, bidi_visual, NULL, NULL, NULL); +#ifdef OLD_FRIBIDI + fribidi_unicode_to_utf8 (bidi_visual, n, utf8str); +#else + fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, bidi_visual, n, utf8str); +#endif + //is_rtl_ = base_dir == FRIBIDI_TYPE_RTL; + //fontIsRightToLeft = base_dir == FRIBIDI_TYPE_RTL; + fontIsRightToLeft = false; + + str_ = std::string(utf8str); + delete[] bidi_logical; + delete[] bidi_visual; + delete[] utf8str; +#endif +} + // =============================================== // class Font2D // =============================================== diff --git a/source/shared_lib/sources/graphics/gl/text_renderer_gl.cpp b/source/shared_lib/sources/graphics/gl/text_renderer_gl.cpp index 06db572f..cc83596d 100644 --- a/source/shared_lib/sources/graphics/gl/text_renderer_gl.cpp +++ b/source/shared_lib/sources/graphics/gl/text_renderer_gl.cpp @@ -20,6 +20,7 @@ #include "string_utils.h" #include "utf8.h" #include "util.h" + #include "leak_dumper.h" using namespace Shared::Util; @@ -58,6 +59,7 @@ void TextRenderer2DGl::render(const string &text, float x, float y, bool centere } string renderText = text; + Font::bidi_cvt(renderText); int line = 0; int size = font->getSize(); const unsigned char *utext = NULL; @@ -388,6 +390,8 @@ void TextRenderer3DGl::render(const string &text, float x, float y, bool center if(text.empty() == false) { string renderText = text; + Font::bidi_cvt(renderText); + if(Font::fontIsMultibyte == true) { if(font->getTextHandler() != NULL) { if(Font::fontIsRightToLeft == true) {