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
This commit is contained in:
auria 2010-05-30 19:11:39 +00:00
parent 4917872611
commit a2825c4b36
8 changed files with 180 additions and 34 deletions

BIN
data/fonts/Rahel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

View File

@ -12,6 +12,7 @@
#include <iostream>
#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<u32> 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<s32>& positi
core::dimension2d<s32> textDimension;
core::position2d<s32> 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<s32>& positi
title_colors, true);
}
else
{
{
driver->draw2DImage(texture,
dest,
source,
clip,
colors, true);
#ifdef FONT_DEBUG
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),
core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y),
video::SColor(255, 255,0,0));
driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y),
core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y),
video::SColor(255, 255,0,0));
driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y),
core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y),
video::SColor(255, 255,0,0));
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),
core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y),
video::SColor(255, 255,0,0));
#endif
}
}
}

View File

@ -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();

View File

@ -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

View File

@ -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 = "<absolute>"; };
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;
};

View File

@ -39,6 +39,10 @@
#include "io/file_manager.hpp"
#include "utils/constants.hpp"
#if ENABLE_BIDI
#include <fribidi.h>
#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;
}

View File

@ -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