From a2825c4b366ed71ade36a8943d727d5019f75ce9 Mon Sep 17 00:00:00 2001 From: auria Date: Sun, 30 May 2010 19:11:39 +0000 Subject: [PATCH] Added support for Hebrew (and, more generally, RTL languages). fribidi must be available and ENABLE_BIDI must be defined (however the autotools build system currently does not check for fribidi presence so if you build with autotools it will always be off) git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5457 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/fonts/Rahel.png | Bin 0 -> 25738 bytes data/fonts/StkFont.xml | Bin 769268 -> 772238 bytes src/guiengine/CGUIFont.cpp | 68 +++++++---- src/guiengine/CGUIFont.h | 9 +- src/ide/Xcode/Config.xcconfig | 4 +- .../Xcode/STK_XCode.xcodeproj/project.pbxproj | 22 +++- src/utils/translation.cpp | 109 +++++++++++++++++- src/utils/translation.hpp | 2 + 8 files changed, 180 insertions(+), 34 deletions(-) create mode 100644 data/fonts/Rahel.png diff --git a/data/fonts/Rahel.png b/data/fonts/Rahel.png new file mode 100644 index 0000000000000000000000000000000000000000..e169110c9fe9ccd9fe33ce3e2e9517d8d17b0612 GIT binary patch literal 25738 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 #include "guiengine/engine.hpp" #include "io/file_manager.hpp" +#include "utils/translation.hpp" namespace irr { @@ -27,7 +28,8 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, const io::path& filename) m_fallback_font_scale = 1.0f; m_fallback_kerning_width = 0; m_is_hollow_copy = false; - + m_rtl = translations->isRTLLanguage(); + m_black_border = false; #ifdef _DEBUG @@ -107,7 +109,7 @@ bool ScalableFont::load(io::IXMLReader* xml) TextureInfo info; info.m_file_name = fn; - info.m_has_alpha = (alpha == core::stringw("false")); + info.m_has_alpha = (alpha == core::stringw("true")); info.m_scale = scale; // disable mipmaps+filtering @@ -197,7 +199,8 @@ bool ScalableFont::load(io::IXMLReader* xml) rectangle.LowerRightCorner.Y = val; CharacterMap[ch] = Areas.size(); - //std::cout << "Inserting character '" << ch << "' with area " << Areas.size() << std::endl; + + //std::cout << "Inserting character '" << (int)ch << "' with area " << Areas.size() << std::endl; // make frame f.rectNumber = SpriteBank->getPositions().size(); @@ -252,24 +255,27 @@ void ScalableFont::setMaxHeight() //! loads a font file, native file needed, for texture parsing + /* bool ScalableFont::load(io::IReadFile* file) { if (!Driver) return false; return loadTexture(Driver->createImageFromFile(file), file->getFileName()); } - +*/ //! loads a font file, native file needed, for texture parsing + /* bool ScalableFont::load(const io::path& filename) { if (!Driver) return false; return loadTexture(Driver->createImageFromFile( filename ), filename); } - +*/ //! load & prepare font from ITexture +#if 0 bool ScalableFont::loadTexture(video::IImage* image, const io::path& name) { if (!image) return false; @@ -313,7 +319,7 @@ bool ScalableFont::loadTexture(video::IImage* image, const io::path& name) flag[1] = Driver->getTextureCreationFlag ( video::ETCF_CREATE_MIP_MAPS ); Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true); - Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false ); + Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true ); SpriteBank->addTexture(Driver->addTexture(name, tmpImage)); @@ -328,9 +334,10 @@ bool ScalableFont::loadTexture(video::IImage* image, const io::path& name) return ret; } +#endif - -void ScalableFont::readPositions(video::IImage* image, s32& lowerRightPositions) +/* +void ScalableFont::readPositions(video::IImage* image, s32& spriteID) { const core::dimension2d size = image->getDimension(); @@ -360,17 +367,17 @@ void ScalableFont::readPositions(video::IImage* image, s32& lowerRightPositions) if (c == colorLowerRight) { // too many lower right points - if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions) + if (SpriteBank->getPositions().size()<=(u32)spriteID) { - lowerRightPositions = 0; + spriteID = 0; return; } image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); - SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos; + SpriteBank->getPositions()[spriteID].LowerRightCorner = pos; // add frame to sprite bank SGUISpriteFrame f; - f.rectNumber = lowerRightPositions; + f.rectNumber = spriteID; f.textureNumber = 0; SGUISprite s; s.Frames.push_back(f); @@ -380,14 +387,14 @@ void ScalableFont::readPositions(video::IImage* image, s32& lowerRightPositions) SFontArea a; a.overhang = 0; a.underhang = 0; - a.spriteno = lowerRightPositions; - a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth(); + a.spriteno = spriteID; + a.width = SpriteBank->getPositions()[spriteID].getWidth(); Areas.push_back(a); // map letter to character - wchar_t ch = (wchar_t)(lowerRightPositions + 32); - CharacterMap[ch] = lowerRightPositions; + wchar_t ch = (wchar_t)(spriteID + 32); + CharacterMap[ch] = spriteID; - ++lowerRightPositions; + ++spriteID; } else if (c == colorBackGround) @@ -395,7 +402,7 @@ void ScalableFont::readPositions(video::IImage* image, s32& lowerRightPositions) } } } - +*/ //! set an Pixel Offset on Drawing ( scale position on width ) void ScalableFont::setKerningWidth(s32 kerning) @@ -460,7 +467,7 @@ s32 ScalableFont::getAreaFromCharacter(const wchar_t c, bool* fallback_font) con } else { - //std::wcout << L"This font does not have this character : <" << c << L">" << std::endl; + std::cout << "The font does not have this character : <" << (int)c << L">" << std::endl; if (fallback_font != NULL) *fallback_font = false; return WrongCharacter; } @@ -556,12 +563,16 @@ void ScalableFont::draw(const core::stringw& text, const core::rect& positi core::dimension2d textDimension; core::position2d offset = position.UpperLeftCorner; - if (hcenter || vcenter || clip) textDimension = getDimension(text.c_str()); + if (m_rtl || hcenter || vcenter || clip) textDimension = getDimension(text.c_str()); if (hcenter) { offset.X += (position.getWidth() - textDimension.Width) / 2; } + else if (m_rtl) + { + offset.X += (position.getWidth() - textDimension.Width); + } if (vcenter) { @@ -776,12 +787,27 @@ void ScalableFont::draw(const core::stringw& text, const core::rect& positi title_colors, true); } else - { + { driver->draw2DImage(texture, dest, source, clip, colors, true); + +#ifdef FONT_DEBUG + driver->draw2DLine(core::position2d(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y), + core::position2d(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y), + video::SColor(255, 255,0,0)); + driver->draw2DLine(core::position2d(dest.LowerRightCorner.X, dest.LowerRightCorner.Y), + core::position2d(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y), + video::SColor(255, 255,0,0)); + driver->draw2DLine(core::position2d(dest.LowerRightCorner.X, dest.LowerRightCorner.Y), + core::position2d(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y), + video::SColor(255, 255,0,0)); + driver->draw2DLine(core::position2d(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y), + core::position2d(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y), + video::SColor(255, 255,0,0)); +#endif } } } diff --git a/src/guiengine/CGUIFont.h b/src/guiengine/CGUIFont.h index ddefc1b6b..02199d60a 100644 --- a/src/guiengine/CGUIFont.h +++ b/src/guiengine/CGUIFont.h @@ -54,6 +54,7 @@ class ScalableFont : public IGUIFontBitmap void lazyLoadTexture(int texID); bool m_is_hollow_copy; + bool m_rtl; public: bool m_black_border; @@ -84,10 +85,10 @@ public: virtual ~ScalableFont(); //! loads a font from a texture file - bool load(const io::path& filename); + //bool load(const io::path& filename); //! loads a font from a texture file - bool load(io::IReadFile* file); + //bool load(io::IReadFile* file); //! loads a font from an XML file bool load(io::IXMLReader* xml); @@ -141,9 +142,9 @@ private: int getCharWidth(const SFontArea& area, const bool fallback) const; //! load & prepare font from ITexture - bool loadTexture(video::IImage * image, const io::path& name); + //bool loadTexture(video::IImage * image, const io::path& name); - void readPositions(video::IImage* texture, s32& lowerRightPositions); + //void readPositions(video::IImage* texture, s32& lowerRightPositions); s32 getAreaFromCharacter (const wchar_t c, bool* fallback_font) const; void setMaxHeight(); diff --git a/src/ide/Xcode/Config.xcconfig b/src/ide/Xcode/Config.xcconfig index 07ffee327..2fb6bbafa 100644 --- a/src/ide/Xcode/Config.xcconfig +++ b/src/ide/Xcode/Config.xcconfig @@ -1,8 +1,8 @@ // Xcode build configuration -HEADER_SEARCH_PATHS = /usr/local/include /usr/include /usr/local/include/irrlicht/ $(PROJECT_DIR)/../../ $(PROJECT_DIR)/../../bullet/src $(PROJECT_DIR)/../../enet/include +HEADER_SEARCH_PATHS = /usr/local/include /usr/include /usr/local/include/irrlicht/ $(PROJECT_DIR)/../../ $(PROJECT_DIR)/../../bullet/src $(PROJECT_DIR)/../../enet/include /Library/Frameworks/fribidi.framework/Headers -OTHER_CFLAGS = -Wall -DHAVE_OGGVORBIS=1 -DHAS_SOCKLEN_T -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAS_POLL=1 -DHAS_FCNTL=1 -DHAS_INET_PTON=1 -DHAS_INET_NTOP=1 -DHAS_MSGHDR_FLAGS=1 -DENABLE_NLS=1 -DHAVE_GETTEXT=1 -DHAVE_GLUT=1 -DHAVE_IRRLICHT=1 -DPACKAGE="\"supertuxkart\"" -D__MACOSX__=1 -DHAVE_RTT=1 +OTHER_CFLAGS = -Wall -DHAVE_OGGVORBIS=1 -DHAS_SOCKLEN_T -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAS_POLL=1 -DHAS_FCNTL=1 -DHAS_INET_PTON=1 -DHAS_INET_NTOP=1 -DHAS_MSGHDR_FLAGS=1 -DENABLE_NLS=1 -DHAVE_GETTEXT=1 -DHAVE_GLUT=1 -DHAVE_IRRLICHT=1 -DPACKAGE="\"supertuxkart\"" -D__MACOSX__=1 -DHAVE_RTT=1 -DENABLE_BIDI=1 OTHER_LDFLAGS = -lirrlicht -lintl LIBRARY_SEARCH_PATHS = /usr/local/lib /usr/lib diff --git a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj index f2427f05b..63c0e00c0 100644 --- a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj +++ b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 953789820FC7831400DD1F8E /* quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953789810FC7831400DD1F8E /* quad.cpp */; }; 953C3CCA10CAF3EE0025F78A /* CGUIFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953C3CC910CAF3EE0025F78A /* CGUIFont.cpp */; }; 95453ACA11808B8700A155B9 /* emergency_animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95453AC811808B8700A155B9 /* emergency_animation.cpp */; }; + 954E486A11B19C4100B1DF63 /* fribidi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 954E486911B19C4100B1DF63 /* fribidi.framework */; }; 954E4C2D0FF98B6F0047FE3E /* animation_base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 954E4C250FF98B6E0047FE3E /* animation_base.cpp */; }; 954E4C2E0FF98B6F0047FE3E /* animation_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 954E4C270FF98B6E0047FE3E /* animation_manager.cpp */; }; 954E4C2F0FF98B6F0047FE3E /* billboard_animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 954E4C290FF98B6E0047FE3E /* billboard_animation.cpp */; }; @@ -257,11 +258,12 @@ 95833240101243ED00C5137E /* player_info_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95833239101243ED00C5137E /* player_info_dialog.cpp */; }; 95833241101243ED00C5137E /* press_a_key_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9583323B101243ED00C5137E /* press_a_key_dialog.cpp */; }; 95833242101243ED00C5137E /* track_info_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9583323D101243ED00C5137E /* track_info_dialog.cpp */; }; + 9586318411B1EC9F00B8B4AF /* grand_prix_lose.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9586318011B1EC9F00B8B4AF /* grand_prix_lose.cpp */; }; + 9586318511B1EC9F00B8B4AF /* grand_prix_win.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9586318211B1EC9F00B8B4AF /* grand_prix_win.cpp */; }; 958BD770117F6AE90095B483 /* music_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 958BD76E117F6AE90095B483 /* music_manager.cpp */; }; 958D8C54104F523000A81934 /* race_paused_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 958D8C53104F523000A81934 /* race_paused_dialog.cpp */; }; 959482D310EBC0790031BADF /* track_object_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 959482CF10EBC0790031BADF /* track_object_manager.cpp */; }; 959482D410EBC0790031BADF /* track_object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 959482D110EBC0790031BADF /* track_object.cpp */; }; - 959D42FD1130C4F2005077E2 /* grand_prix_over.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 959D42FB1130C4F2005077E2 /* grand_prix_over.cpp */; }; 95B5CD14102DE08F00EF2001 /* device_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95B5CD13102DE08F00EF2001 /* device_config.cpp */; }; 95C77D631069589B0080838E /* ambient_light_sphere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95C77D621069589B0080838E /* ambient_light_sphere.cpp */; }; 95C77D66106958A50080838E /* check_line.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95C77D65106958A50080838E /* check_line.cpp */; }; @@ -393,6 +395,7 @@ 9540E2570FD5F8FD002985B8 /* no_copy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = no_copy.hpp; path = ../../utils/no_copy.hpp; sourceTree = SOURCE_ROOT; }; 95453AC811808B8700A155B9 /* emergency_animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = emergency_animation.cpp; path = ../../karts/emergency_animation.cpp; sourceTree = SOURCE_ROOT; }; 95453AC911808B8700A155B9 /* emergency_animation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = emergency_animation.hpp; path = ../../karts/emergency_animation.hpp; sourceTree = SOURCE_ROOT; }; + 954E486911B19C4100B1DF63 /* fribidi.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = fribidi.framework; path = /Library/Frameworks/fribidi.framework; sourceTree = ""; }; 954E4C250FF98B6E0047FE3E /* animation_base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = animation_base.cpp; path = ../../animations/animation_base.cpp; sourceTree = SOURCE_ROOT; }; 954E4C260FF98B6E0047FE3E /* animation_base.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = animation_base.hpp; path = ../../animations/animation_base.hpp; sourceTree = SOURCE_ROOT; }; 954E4C270FF98B6E0047FE3E /* animation_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = animation_manager.cpp; path = ../../animations/animation_manager.cpp; sourceTree = SOURCE_ROOT; }; @@ -473,6 +476,10 @@ 9583323C101243ED00C5137E /* press_a_key_dialog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = press_a_key_dialog.hpp; path = ../../states_screens/dialogs/press_a_key_dialog.hpp; sourceTree = SOURCE_ROOT; }; 9583323D101243ED00C5137E /* track_info_dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = track_info_dialog.cpp; path = ../../states_screens/dialogs/track_info_dialog.cpp; sourceTree = SOURCE_ROOT; }; 9583323E101243ED00C5137E /* track_info_dialog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = track_info_dialog.hpp; path = ../../states_screens/dialogs/track_info_dialog.hpp; sourceTree = SOURCE_ROOT; }; + 9586318011B1EC9F00B8B4AF /* grand_prix_lose.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = grand_prix_lose.cpp; path = ../../states_screens/grand_prix_lose.cpp; sourceTree = SOURCE_ROOT; }; + 9586318111B1EC9F00B8B4AF /* grand_prix_lose.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = grand_prix_lose.hpp; path = ../../states_screens/grand_prix_lose.hpp; sourceTree = SOURCE_ROOT; }; + 9586318211B1EC9F00B8B4AF /* grand_prix_win.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = grand_prix_win.cpp; path = ../../states_screens/grand_prix_win.cpp; sourceTree = SOURCE_ROOT; }; + 9586318311B1EC9F00B8B4AF /* grand_prix_win.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = grand_prix_win.hpp; path = ../../states_screens/grand_prix_win.hpp; sourceTree = SOURCE_ROOT; }; 958BD76E117F6AE90095B483 /* music_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = music_manager.cpp; path = ../../audio/music_manager.cpp; sourceTree = SOURCE_ROOT; }; 958BD76F117F6AE90095B483 /* music_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = music_manager.hpp; path = ../../audio/music_manager.hpp; sourceTree = SOURCE_ROOT; }; 958D8C52104F523000A81934 /* race_paused_dialog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = race_paused_dialog.hpp; path = ../../states_screens/dialogs/race_paused_dialog.hpp; sourceTree = SOURCE_ROOT; }; @@ -481,8 +488,6 @@ 959482D010EBC0790031BADF /* track_object_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = track_object_manager.hpp; path = ../../tracks/track_object_manager.hpp; sourceTree = SOURCE_ROOT; }; 959482D110EBC0790031BADF /* track_object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = track_object.cpp; path = ../../tracks/track_object.cpp; sourceTree = SOURCE_ROOT; }; 959482D210EBC0790031BADF /* track_object.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = track_object.hpp; path = ../../tracks/track_object.hpp; sourceTree = SOURCE_ROOT; }; - 959D42FB1130C4F2005077E2 /* grand_prix_over.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = grand_prix_over.cpp; path = ../../states_screens/grand_prix_over.cpp; sourceTree = SOURCE_ROOT; }; - 959D42FC1130C4F2005077E2 /* grand_prix_over.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = grand_prix_over.hpp; path = ../../states_screens/grand_prix_over.hpp; sourceTree = SOURCE_ROOT; }; 95A118290F77EA3100B18B3D /* input.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = input.hpp; path = ../../input/input.hpp; sourceTree = SOURCE_ROOT; }; 95A1182A0F77EA3100B18B3D /* input_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = input_manager.cpp; path = ../../input/input_manager.cpp; sourceTree = SOURCE_ROOT; }; 95A1182B0F77EA3100B18B3D /* input_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = input_manager.hpp; path = ../../input/input_manager.hpp; sourceTree = SOURCE_ROOT; }; @@ -1082,6 +1087,7 @@ 9551C9F10FC1B7EE00DB481B /* Ogg.framework in Frameworks */, 9551C9F20FC1B7EE00DB481B /* OpenAL.framework in Frameworks */, 9551C9F30FC1B7EE00DB481B /* Vorbis.framework in Frameworks */, + 954E486A11B19C4100B1DF63 /* fribidi.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1114,6 +1120,7 @@ 9513B40E0F0EDE80005D29F6 /* Frameworks */ = { isa = PBXGroup; children = ( + 954E486911B19C4100B1DF63 /* fribidi.framework */, 9551CBD90FC1BB9200DB481B /* AGL.framework */, 9551C7F90FC1B63C00DB481B /* Ogg.framework */, 9551C7FA0FC1B63C00DB481B /* OpenAL.framework */, @@ -1265,8 +1272,10 @@ 958330C310122B4A00C5137E /* credits.hpp */, 95D2343E1078227A00625256 /* feature_unlocked.cpp */, 95D2343D1078227A00625256 /* feature_unlocked.hpp */, - 959D42FB1130C4F2005077E2 /* grand_prix_over.cpp */, - 959D42FC1130C4F2005077E2 /* grand_prix_over.hpp */, + 9586318011B1EC9F00B8B4AF /* grand_prix_lose.cpp */, + 9586318111B1EC9F00B8B4AF /* grand_prix_lose.hpp */, + 9586318211B1EC9F00B8B4AF /* grand_prix_win.cpp */, + 9586318311B1EC9F00B8B4AF /* grand_prix_win.hpp */, 9522F1DE10795E8A0067ECF5 /* help_screen_1.cpp */, 9522F1DF10795E8A0067ECF5 /* help_screen_1.hpp */, 9522F1E210795EFF0067ECF5 /* help_screen_2.cpp */, @@ -2540,7 +2549,6 @@ 956C6ED51128D3FB004336C8 /* end_controller.cpp in Sources */, 956C6ED61128D3FB004336C8 /* new_ai_controller.cpp in Sources */, 956C6ED71128D3FB004336C8 /* player_controller.cpp in Sources */, - 959D42FD1130C4F2005077E2 /* grand_prix_over.cpp in Sources */, 956830E01132EC9E00088D14 /* irr_debug_drawer.cpp in Sources */, 957ED4801163FF18002AB42C /* ai_base_controller.cpp in Sources */, 958BD770117F6AE90095B483 /* music_manager.cpp in Sources */, @@ -2549,6 +2557,8 @@ 950D45D1118E040E006CFC41 /* options_screen_input2.cpp in Sources */, 9556A880119EF976009C558F /* options_screen_audio.cpp in Sources */, 9556A881119EF976009C558F /* options_screen_video.cpp in Sources */, + 9586318411B1EC9F00B8B4AF /* grand_prix_lose.cpp in Sources */, + 9586318511B1EC9F00B8B4AF /* grand_prix_win.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/utils/translation.cpp b/src/utils/translation.cpp index 27c8eca3e..e3e6eea09 100644 --- a/src/utils/translation.cpp +++ b/src/utils/translation.cpp @@ -39,6 +39,10 @@ #include "io/file_manager.hpp" #include "utils/constants.hpp" +#if ENABLE_BIDI +#include +#endif + // set to 1 to debug i18n #define TRANSLATE_VERBOSE 0 @@ -49,6 +53,7 @@ bool remove_bom = false; Translations::Translations() { #ifdef ENABLE_NLS + // LC_ALL does not work, sscanf will then not always be able // to scan for example: s=-1.1,-2.3,-3.3 correctly, which is // used in driveline files. @@ -58,7 +63,45 @@ Translations::Translations() #else setlocale(LC_MESSAGES, ""); #endif + + // FIXME: I couldn't find a way to ask gettext what language it currently uses xD that's the closest I found + const char* language = getenv("LANGUAGE"); + const char* lc_all = getenv("LC_ALL"); + const char* lc_type = getenv("LC_CTYPE"); + const char* lc_msg = getenv("LC_MESSAGES"); + const char* lang = getenv("LANG"); + + const char* firstNonNull = NULL; + if (language != NULL) firstNonNull = language; + else if (lc_all != NULL) firstNonNull = lc_all; + else if (lc_type != NULL) firstNonNull = lc_type; + else if (lc_msg != NULL) firstNonNull = lc_msg; + else if (lang != NULL) firstNonNull = lang; + + if (firstNonNull != NULL) + { + if (strcmp(firstNonNull, "he") == 0 || strcmp(firstNonNull, "yi") == 0) + { + // Hebrew + m_rtl = true; + } + else if (strcmp(firstNonNull, "ar") == 0 || strcmp(firstNonNull, "az") == 0) + { + // Arabic + m_rtl = true; + } + else + { + m_rtl = false; + } + } + else + { + m_rtl = false; + } + bindtextdomain (PACKAGE, file_manager->getTranslationDir().c_str()); + if (sizeof(wchar_t) == 4) { // FIXME: will probably not work on PPC maccs @@ -131,9 +174,73 @@ const wchar_t* Translations::w_gettext(const char* original) wchar_t* out_ptr = (wchar_t*)original_t; if (remove_bom) out_ptr++; + #if TRANSLATE_VERBOSE std::wcout << L" translation : " << out_ptr << std::endl; #endif - return out_ptr; + + +#if ENABLE_BIDI + + const int FRIBIDI_BUFFER_SIZE = 512; + FriBidiChar fribidiInput[FRIBIDI_BUFFER_SIZE]; + + int len = 0; + int n = 0; + //std::cout << "fribidi input : "; + for (n = 0; ; n++) + { + fribidiInput[n] = out_ptr[n]; + //std::cout << (int)fribidiInput[n] << " "; + len++; + + if (n == FRIBIDI_BUFFER_SIZE-1) // prevent buffeoverflows + { + std::cerr << "WARNING : translated stirng too long, truncating!\n"; + fribidiInput[n] = 0; + break; + } + if (fribidiInput[n] == 0) break; // stop on '\0' + } + //std::cout << " (len=" << len << ")\n"; + FriBidiCharType pbase_dir = FRIBIDI_TYPE_ON; //FIXME: what's that? + + static FriBidiChar fribidiOutput[FRIBIDI_BUFFER_SIZE]; + + fribidi_boolean result = fribidi_log2vis(fribidiInput, + len-1, + &pbase_dir, + fribidiOutput, + /* gint *position_L_to_V_list */ NULL, + /* gint *position_V_to_L_list */ NULL, + /* gint8 *embedding_level_list */ NULL + ); + + if (!result) + { + std::cerr << "Fribidi failed in 'fribidi_log2vis' =(\n"; + } + + //std::cout << "fribidi output : "; + //for (FriBidiChar* c=fribidiOutput; *c != 0; c++) + //{ + // std::cout << (int)fribidiOutput[n] << " "; + //} + //std::cout << "\n"; + + + return (const wchar_t*)fribidiOutput; + +#else + + return out_ptr; + +#endif } + +bool Translations::isRTLLanguage() const +{ + return m_rtl; +} + diff --git a/src/utils/translation.hpp b/src/utils/translation.hpp index 581ad72fd..8f109c777 100644 --- a/src/utils/translation.hpp +++ b/src/utils/translation.hpp @@ -46,9 +46,11 @@ class Translations { private: irr::core::stringw m_converted_string; + bool m_rtl; public: Translations(); const wchar_t *w_gettext(const char* original); + bool isRTLLanguage() const; }; // Translations