From fc3f5bbfa05486b09c73615ecd4ca7b9b2cf4663 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Thu, 9 Jun 2011 05:54:04 +0000 Subject: [PATCH] - added some logic to 'try' to figure out when to render font test right to left and when not to --- source/glest_game/main/main.cpp | 16 +++- source/shared_lib/include/graphics/font.h | 1 + source/shared_lib/include/util/string_utils.h | 5 ++ source/shared_lib/include/util/utf8/core.h | 74 +++++++++++++++++++ source/shared_lib/sources/graphics/font.cpp | 1 + .../sources/graphics/gl/text_renderer_gl.cpp | 73 +++++++++++------- source/shared_lib/sources/util/properties.cpp | 5 ++ .../shared_lib/sources/util/string_utils.cpp | 55 ++++++++++++++ 8 files changed, 202 insertions(+), 28 deletions(-) diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index 6cb532c72..e826040a6 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -2466,6 +2466,8 @@ int glestMain(int argc, char** argv) { Font::charCount = config.getInt("FONT_CHARCOUNT",intToStr(Font::charCount).c_str()); Font::fontTypeName = config.getString("FONT_TYPENAME",Font::fontTypeName.c_str()); Font::fontIsMultibyte = config.getBool("FONT_MULTIBYTE",intToStr(Font::fontIsMultibyte).c_str()); + Font::fontIsRightToLeft = config.getBool("FONT_RIGHTTOLEFT",intToStr(Font::fontIsRightToLeft).c_str()); + // Example values: // DEFAULT_CHARSET (English) = 1 // GB2312_CHARSET (Chinese) = 134 @@ -2487,7 +2489,7 @@ int glestMain(int argc, char** argv) { // Setup debug logging etc setupLogging(config, haveSpecialOutputCommandLineOption); - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::charSet = %d, Font::fontIsMultibyte = %d\n",__FILE__,__FUNCTION__,__LINE__,Font::charCount,Font::fontTypeName.c_str(),Shared::Platform::charSet,Font::fontIsMultibyte); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::charSet = %d, Font::fontIsMultibyte = %d, fontIsRightToLeft = %d\n",__FILE__,__FUNCTION__,__LINE__,Font::charCount,Font::fontTypeName.c_str(),Shared::Platform::charSet,Font::fontIsMultibyte, Font::fontIsRightToLeft); NetworkInterface::setDisplayMessageFunction(ExceptionHandler::DisplayMessage); MenuStateMasterserver::setDisplayMessageFunction(ExceptionHandler::DisplayMessage); @@ -2573,6 +2575,10 @@ int glestMain(int argc, char** argv) { Font::fontIsMultibyte = strToBool(lang.get("FONT_MULTIBYTE")); } + if( lang.hasString("FONT_RIGHTTOLEFT")) { + Font::fontIsRightToLeft = strToBool(lang.get("FONT_RIGHTTOLEFT")); + } + if( lang.hasString("MEGAGLEST_FONT")) { //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/ttf-japanese-gothic.ttf",0); // Japanese #if defined(WIN32) @@ -2606,6 +2612,10 @@ int glestMain(int argc, char** argv) { if( lang.hasString("FONT_MULTIBYTE_WINDOWS")) { Font::fontIsMultibyte = strToBool(lang.get("FONT_MULTIBYTE_WINDOWS")); } + if( lang.hasString("FONT_RIGHTTOLEFT_WINDOWS")) { + Font::fontIsRightToLeft = strToBool(lang.get("FONT_RIGHTTOLEFT_WINDOWS")); + } + if( lang.hasString("MEGAGLEST_FONT_WINDOWS")) { //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/ttf-japanese-gothic.ttf",0); // Japanese string newEnvValue = "MEGAGLEST_FONT=" + lang.get("MEGAGLEST_FONT_WINDOWS"); @@ -2618,8 +2628,8 @@ int glestMain(int argc, char** argv) { // end win32 #endif - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::charSet = %d, Font::fontIsMultibyte = %d\n",__FILE__,__FUNCTION__,__LINE__,Font::charCount,Font::fontTypeName.c_str(),Shared::Platform::charSet,Font::fontIsMultibyte); - if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::charSet = %d, Font::fontIsMultibyte = %d\n",Font::charCount,Font::fontTypeName.c_str(),Shared::Platform::charSet,Font::fontIsMultibyte); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::charSet = %d, Font::fontIsMultibyte = %d, Font::fontIsRightToLeft = %d\n",__FILE__,__FUNCTION__,__LINE__,Font::charCount,Font::fontTypeName.c_str(),Shared::Platform::charSet,Font::fontIsMultibyte,Font::fontIsRightToLeft); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::charSet = %d, Font::fontIsMultibyte = %d, Font::fontIsRightToLeft = %d\n",Font::charCount,Font::fontTypeName.c_str(),Shared::Platform::charSet,Font::fontIsMultibyte,Font::fontIsRightToLeft); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); diff --git a/source/shared_lib/include/graphics/font.h b/source/shared_lib/include/graphics/font.h index a0ddef906..74ac29345 100644 --- a/source/shared_lib/include/graphics/font.h +++ b/source/shared_lib/include/graphics/font.h @@ -64,6 +64,7 @@ public: static std::string fontTypeName; static bool fontIsMultibyte; static bool forceLegacyFonts; + static bool fontIsRightToLeft; public: enum Width { diff --git a/source/shared_lib/include/util/string_utils.h b/source/shared_lib/include/util/string_utils.h index b8656f6a4..89490282a 100644 --- a/source/shared_lib/include/util/string_utils.h +++ b/source/shared_lib/include/util/string_utils.h @@ -610,6 +610,11 @@ namespace Shared { namespace Util { }; + void strrev(char *p); + void strrev_utf8(char *p); + void strrev_utf8(std::string &p); + bool is_string_all_ascii(std::string str); + }} // namespace TA3D #endif // _SHARED_UTIL_W_STRING_H__ diff --git a/source/shared_lib/include/util/utf8/core.h b/source/shared_lib/include/util/utf8/core.h index 268cf7cd4..a4a2d93de 100755 --- a/source/shared_lib/include/util/utf8/core.h +++ b/source/shared_lib/include/util/utf8/core.h @@ -351,6 +351,80 @@ namespace internal (internal::mask8(*it)) == bom[2] ); } + + +/* + //const uint8_t rlm[] = {0xe2, 0x80, 0x8f}; + const uint8_t rlm1[] = {0x20, 0x0f}; + const uint8_t rlm2[] = {0x20, 0x2b}; + const uint8_t rlm3[] = {0x20, 0x2e}; + + template + inline bool starts_with_rlm (octet_iterator it, octet_iterator end) + { + int rlmMatchCount = 0; + uint32_t code_point = 0; + octet_iterator result = it; + while (result != end) { + internal::utf_error err_code = internal::validate_next(result, end, &code_point); + if (err_code != internal::UTF8_OK) { + return false; + } + else { + + if( (code_point == rlm1[0] && rlmMatchCount == 0) || + (code_point == rlm1[1] && rlmMatchCount == 1)) { + //printf("#1 FOUND rlm: [%X][%c]\n",code_point,code_point); + rlmMatchCount++; + } + else if( (code_point == rlm2[0] && rlmMatchCount == 0) || + (code_point == rlm2[1] && rlmMatchCount == 1)) { + //printf("#2 FOUND rlm: [%X][%c]\n",code_point,code_point); + rlmMatchCount++; + } + else if( (code_point == rlm3[0] && rlmMatchCount == 0) || + (code_point == rlm3[1] && rlmMatchCount == 1)) { + //printf("#3 FOUND rlm: [%X][%c]\n",code_point,code_point); + rlmMatchCount++; + } + else { + rlmMatchCount = 0; + } + + if(rlmMatchCount == 2) { + return true; + } + + //if(rlmMatchCount == 0 && code_point == rlm[0]) { + // rlmMatchCount++; + //} + //if(rlmMatchCount == 1 && code_point == rlm[1]) { + // rlmMatchCount++; + // return true; + //} +// if(rlmMatchCount == 2 && code_point == rlm[2]) { +// rlmMatchCount++; +// +// return true; +// } + +// if(((result != end) && (internal::mask8(*result)) == rlm[0]) && +// ((result != end) && (internal::mask8(*result + 1)) == rlm[1]) && +// ((result != end) && (internal::mask8(*result + 2)) == rlm[2])) { +// return true; +// } + + } + } + return false; + +// return ( +// ((it != end) && (internal::mask8(*it++)) == rlm[0]) && +// ((it != end) && (internal::mask8(*it++)) == rlm[1]) && +// ((it != end) && (internal::mask8(*it)) == rlm[2]) +// ); + } +*/ } // namespace utf8 #endif // header guard diff --git a/source/shared_lib/sources/graphics/font.cpp b/source/shared_lib/sources/graphics/font.cpp index 7dc9655e3..87de94fa1 100644 --- a/source/shared_lib/sources/graphics/font.cpp +++ b/source/shared_lib/sources/graphics/font.cpp @@ -37,6 +37,7 @@ std::string Font::fontTypeName = "Times New Roman"; bool Font::fontIsMultibyte = false; bool Font::forceLegacyFonts = false; float FontMetrics::DEFAULT_Y_OFFSET_FACTOR = 8.0f; +bool Font::fontIsRightToLeft = false; // // ===================================================== 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 7b6c29477..4c7e6058e 100644 --- a/source/shared_lib/sources/graphics/gl/text_renderer_gl.cpp +++ b/source/shared_lib/sources/graphics/gl/text_renderer_gl.cpp @@ -17,8 +17,12 @@ #include "font_text.h" #include #include +#include "string_utils.h" +#include "utf8.h" #include "leak_dumper.h" +using namespace Shared::Util; + namespace Shared { namespace Graphics { namespace Gl { // ===================================================== @@ -57,21 +61,6 @@ void TextRenderer2DGl::begin(Font2D *font) { rendering = true; } -// Convert a narrow string to a wide string// -//std::wstring widen(const std::string& str) { -// // Make space for wide string -// wchar_t* buffer = new wchar_t[str.size() + 1]; -// // convert ASCII to UNICODE -// mbstowcs( buffer, str.c_str(), str.size() ); -// // NULL terminate it -// buffer[str.size()] = 0; -// // Clean memory and return it -// std::wstring wstr = buffer; -// delete [] buffer; -// return wstr; -//} -// Widen an individual character - void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, Vec3f *color) { //tester->render(text, x, y, this->font->getWidth(),centered); //return; @@ -116,11 +105,32 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V } glRasterPos2f(rasterPos.x, rasterPos.y); + //fontFTGL->Render("مرحبا العالم"); //Arabic Works! + //wstring temp = L"المدى"; + //temp = wstring (temp.rbegin(), temp.rend()); + //font->getTextHandler()->Render(temp.c_str()); + //return; + //font->getTextHandler()->Render("Zurück"); //return; if(Font::fontIsMultibyte == true) { if(font->getTextHandler() != NULL) { + string renderText = text; + if(Font::fontIsRightToLeft == true) { + //printf("\n\n#A [%s]\n",renderText.c_str()); + //bool isRLM = utf8::starts_with_rlm(text.begin(), text.end() + text.size()); + + //printf("\n\nORIGINAL TEXT [%s] isRLM = %d\n\n",text.c_str(),isRLM); + //for(int i = 0; i < renderText.size(); ++i) { + // printf("i = %d c [%c][%d][%X]\n",i,renderText[i],renderText[i],renderText[i]); + //} + //if(isRLM == true) { + if(is_string_all_ascii(renderText) == false) { + strrev_utf8(renderText); + } + } + //String str("資料"); //WString wstr(str); //fontFTGL->Render(wstr.cw_str()); @@ -169,19 +179,19 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V // This works //fontFTGL->Render(text.c_str()); - if(text.find("\n") == text.npos && text.find("\t") == text.npos) { - font->getTextHandler()->Render(text.c_str()); + if(renderText.find("\n") == renderText.npos && renderText.find("\t") == renderText.npos) { + font->getTextHandler()->Render(renderText.c_str()); } else { bool lastCharacterWasSpecial = true; vector parts; char szBuf[4096]=""; - for (int i=0; text[i] != '\0'; ++i) { + for (int i=0; renderText[i] != '\0'; ++i) { szBuf[0] = '\0'; - sprintf(szBuf,"%c",text[i]); + sprintf(szBuf,"%c",renderText[i]); - switch(text[i]) { + switch(renderText[i]) { case '\t': parts.push_back(szBuf); lastCharacterWasSpecial = true; @@ -236,6 +246,12 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V //glCallLists(utfText.length(), GL_UNSIGNED_SHORT, &utfText[0]); string utfText = text; + if(Font::fontIsRightToLeft == true) { + if(is_string_all_ascii(utfText) == false) { + strrev_utf8(utfText); + } + } + glListBase(font->getHandle()); glCallLists(text.length(), GL_UNSIGNED_SHORT, &utext[0]); @@ -250,19 +266,26 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V } else { if(font->getTextHandler() != NULL) { - if(text.find("\n") == text.npos && text.find("\t") == text.npos) { - font->getTextHandler()->Render(text.c_str()); + string renderText = text; + if(Font::fontIsRightToLeft == true) { + if(is_string_all_ascii(renderText) == false) { + strrev_utf8(renderText); + } + } + + if(renderText.find("\n") == renderText.npos && renderText.find("\t") == renderText.npos) { + font->getTextHandler()->Render(renderText.c_str()); } else { bool lastCharacterWasSpecial = true; vector parts; char szBuf[4096]=""; - for (int i=0; text[i] != '\0'; ++i) { + for (int i=0; renderText[i] != '\0'; ++i) { szBuf[0] = '\0'; - sprintf(szBuf,"%c",text[i]); + sprintf(szBuf,"%c",renderText[i]); - switch(text[i]) { + switch(renderText[i]) { case '\t': parts.push_back(szBuf); lastCharacterWasSpecial = true; diff --git a/source/shared_lib/sources/util/properties.cpp b/source/shared_lib/sources/util/properties.cpp index 433770bc4..4345c0a65 100644 --- a/source/shared_lib/sources/util/properties.cpp +++ b/source/shared_lib/sources/util/properties.cpp @@ -299,6 +299,11 @@ void Properties::load(const string &path, bool clearCurrentProperties) { memcpy(&lineBuffer[0],&utfStr[0],strlen(utfStr)); } +// bool isRLM = utf8::starts_with_rlm(&lineBuffer[0], &lineBuffer[0] + strlen(lineBuffer)); +// if(isRLM) { +// printf("\n\nORIGINAL TEXT [%s] isRLM = %d\n\n",&lineBuffer[0],isRLM); +// } + //if(is_utf8_language == true && Font::forceLegacyFonts == true) { //string line = lineBuffer; //wstring wstr = fromUtf8(line.c_str(), line.size()); diff --git a/source/shared_lib/sources/util/string_utils.cpp b/source/shared_lib/sources/util/string_utils.cpp index 095252d4f..633ed0b88 100644 --- a/source/shared_lib/sources/util/string_utils.cpp +++ b/source/shared_lib/sources/util/string_utils.cpp @@ -691,4 +691,59 @@ namespace Shared { namespace Util { pBuffer[len] = 0; } + + void strrev(char *p) { + char *q = p; + while(q && *q) ++q; + for(--q; p < q; ++p, --q) + *p = *p ^ *q, + *q = *p ^ *q, + *p = *p ^ *q; + } + + #define SWP(x,y) (x^=y, y^=x, x^=y) + + void strrev_utf8(char *p) { + char *q = p; + strrev(p); /* call base case */ + + /* Ok, now fix bass-ackwards UTF chars. */ + while(q && *q) ++q; /* find eos */ + while(p < --q) + switch( (*q & 0xF0) >> 4 ) { + case 0xF: /* U+010000-U+10FFFF: four bytes. */ + SWP(*(q-0), *(q-3)); + SWP(*(q-1), *(q-2)); + q -= 3; + break; + case 0xE: /* U+000800-U+00FFFF: three bytes. */ + SWP(*(q-0), *(q-2)); + q -= 2; + break; + case 0xC: /* fall-through */ + case 0xD: /* U+000080-U+0007FF: two bytes. */ + SWP(*(q-0), *(q-1)); + q--; + break; + } + } + + void strrev_utf8(std::string &p) { + char szBuf[p.size()+1]; + strcpy(szBuf,p.c_str()); + szBuf[p.size()+1] = '\0'; + strrev_utf8(&szBuf[0]); + p = szBuf; + } + + bool is_string_all_ascii(std::string str) { + bool result = true; + for(int i = 0; i < str.length(); ++i) { + if(isascii(str[i]) == false) { + result = false; + break; + } + } + return result; + } }}