- added some bug fixes to check if lng files are utf-8 or not and deal with it appropriately
This commit is contained in:
parent
bf9702cdca
commit
f65bfe8710
|
@ -133,6 +133,8 @@ void CoreData::load() {
|
||||||
string displayFontNamePostfix = config.getString("FontDisplayPostfix");
|
string displayFontNamePostfix = config.getString("FontDisplayPostfix");
|
||||||
int displayFontSize = computeFontSize(config.getInt("FontDisplayBaseSize"));
|
int displayFontSize = computeFontSize(config.getInt("FontDisplayBaseSize"));
|
||||||
|
|
||||||
|
//printf("Checking if langfile has custom FontDisplayPostfix\n");
|
||||||
|
|
||||||
if(lang.hasString("FontDisplayPrefix") == true) {
|
if(lang.hasString("FontDisplayPrefix") == true) {
|
||||||
displayFontNamePrefix = lang.get("FontDisplayPrefix");
|
displayFontNamePrefix = lang.get("FontDisplayPrefix");
|
||||||
}
|
}
|
||||||
|
@ -143,11 +145,19 @@ void CoreData::load() {
|
||||||
displayFontSize = strToInt(lang.get("FontDisplayBaseSize"));
|
displayFontSize = strToInt(lang.get("FontDisplayBaseSize"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//printf("displayFontNamePostfix [%s]\n",displayFontNamePostfix.c_str());
|
||||||
|
|
||||||
string displayFontName = displayFontNamePrefix + intToStr(displayFontSize) + displayFontNamePostfix;
|
string displayFontName = displayFontNamePrefix + intToStr(displayFontSize) + displayFontNamePostfix;
|
||||||
|
|
||||||
displayFont= renderer.newFont(rsGlobal);
|
displayFont= renderer.newFont(rsGlobal);
|
||||||
displayFont->setType(displayFontName,config.getString("FontDisplay",""));
|
displayFont->setType(displayFontName,config.getString("FontDisplay",""));
|
||||||
displayFont->setSize(displayFontSize);
|
displayFont->setSize(displayFontSize);
|
||||||
|
displayFont->setYOffsetFactor(config.getFloat("FontDisplayYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
|
displayFont3D= renderer.newFont3D(rsGlobal);
|
||||||
|
displayFont3D->setType(displayFontName,config.getString("FontDisplay",""));
|
||||||
|
displayFont3D->setSize(displayFontSize);
|
||||||
|
displayFont3D->setYOffsetFactor(config.getFloat("FontDisplayYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] displayFontName = [%s] displayFontSize = %d\n",__FILE__,__FUNCTION__,__LINE__,displayFontName.c_str(),displayFontSize);
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] displayFontName = [%s] displayFontSize = %d\n",__FILE__,__FUNCTION__,__LINE__,displayFontName.c_str(),displayFontSize);
|
||||||
|
|
||||||
|
@ -167,9 +177,16 @@ void CoreData::load() {
|
||||||
}
|
}
|
||||||
|
|
||||||
string displayFontNameSmall = displayFontNameSmallPrefix + intToStr(displayFontNameSmallSize) + displayFontNameSmallPostfix;
|
string displayFontNameSmall = displayFontNameSmallPrefix + intToStr(displayFontNameSmallSize) + displayFontNameSmallPostfix;
|
||||||
|
|
||||||
displayFontSmall= renderer.newFont(rsGlobal);
|
displayFontSmall= renderer.newFont(rsGlobal);
|
||||||
displayFontSmall->setType(displayFontNameSmall,config.getString("FontDisplay",""));
|
displayFontSmall->setType(displayFontNameSmall,config.getString("FontSmallDisplay",""));
|
||||||
displayFontSmall->setSize(displayFontNameSmallSize);
|
displayFontSmall->setSize(displayFontNameSmallSize);
|
||||||
|
displayFontSmall->setYOffsetFactor(config.getFloat("FontSmallDisplayYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
|
displayFontSmall3D= renderer.newFont3D(rsGlobal);
|
||||||
|
displayFontSmall3D->setType(displayFontNameSmall,config.getString("FontSmallDisplay",""));
|
||||||
|
displayFontSmall3D->setSize(displayFontNameSmallSize);
|
||||||
|
displayFontSmall3D->setYOffsetFactor(config.getFloat("FontSmallDisplayYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] displayFontSmallName = [%s] displayFontSmallNameSize = %d\n",__FILE__,__FUNCTION__,__LINE__,displayFontNameSmall.c_str(),displayFontNameSmallSize);
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] displayFontSmallName = [%s] displayFontSmallNameSize = %d\n",__FILE__,__FUNCTION__,__LINE__,displayFontNameSmall.c_str(),displayFontNameSmallSize);
|
||||||
|
|
||||||
|
@ -188,10 +205,18 @@ void CoreData::load() {
|
||||||
}
|
}
|
||||||
|
|
||||||
string menuFontNameNormal= menuFontNameNormalPrefix + intToStr(menuFontNameNormalSize) + menuFontNameNormalPostfix;
|
string menuFontNameNormal= menuFontNameNormalPrefix + intToStr(menuFontNameNormalSize) + menuFontNameNormalPostfix;
|
||||||
|
|
||||||
menuFontNormal= renderer.newFont(rsGlobal);
|
menuFontNormal= renderer.newFont(rsGlobal);
|
||||||
menuFontNormal->setType(menuFontNameNormal,config.getString("FontMenuNormal",""));
|
menuFontNormal->setType(menuFontNameNormal,config.getString("FontMenuNormal",""));
|
||||||
menuFontNormal->setSize(menuFontNameNormalSize);
|
menuFontNormal->setSize(menuFontNameNormalSize);
|
||||||
menuFontNormal->setWidth(Font::wBold);
|
menuFontNormal->setWidth(Font::wBold);
|
||||||
|
menuFontNormal->setYOffsetFactor(config.getFloat("FontMenuNormalYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
|
menuFontNormal3D= renderer.newFont3D(rsGlobal);
|
||||||
|
menuFontNormal3D->setType(menuFontNameNormal,config.getString("FontMenuNormal",""));
|
||||||
|
menuFontNormal3D->setSize(menuFontNameNormalSize);
|
||||||
|
menuFontNormal3D->setWidth(Font::wBold);
|
||||||
|
menuFontNormal3D->setYOffsetFactor(config.getFloat("FontMenuNormalYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] menuFontNormalName = [%s] menuFontNormalNameSize = %d\n",__FILE__,__FUNCTION__,__LINE__,menuFontNameNormal.c_str(),menuFontNameNormalSize);
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] menuFontNormalName = [%s] menuFontNormalNameSize = %d\n",__FILE__,__FUNCTION__,__LINE__,menuFontNameNormal.c_str(),menuFontNameNormalSize);
|
||||||
|
|
||||||
|
@ -214,6 +239,12 @@ void CoreData::load() {
|
||||||
menuFontBig= renderer.newFont(rsGlobal);
|
menuFontBig= renderer.newFont(rsGlobal);
|
||||||
menuFontBig->setType(menuFontNameBig,config.getString("FontMenuBig",""));
|
menuFontBig->setType(menuFontNameBig,config.getString("FontMenuBig",""));
|
||||||
menuFontBig->setSize(menuFontNameBigSize);
|
menuFontBig->setSize(menuFontNameBigSize);
|
||||||
|
menuFontBig->setYOffsetFactor(config.getFloat("FontMenuBigYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
|
menuFontBig3D= renderer.newFont3D(rsGlobal);
|
||||||
|
menuFontBig3D->setType(menuFontNameBig,config.getString("FontMenuBig",""));
|
||||||
|
menuFontBig3D->setSize(menuFontNameBigSize);
|
||||||
|
menuFontBig3D->setYOffsetFactor(config.getFloat("FontMenuBigYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] menuFontNameBig = [%s] menuFontNameBigSize = %d\n",__FILE__,__FUNCTION__,__LINE__,menuFontNameBig.c_str(),menuFontNameBigSize);
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] menuFontNameBig = [%s] menuFontNameBigSize = %d\n",__FILE__,__FUNCTION__,__LINE__,menuFontNameBig.c_str(),menuFontNameBigSize);
|
||||||
|
|
||||||
|
@ -234,8 +265,14 @@ void CoreData::load() {
|
||||||
string menuFontNameVeryBig= menuFontNameVeryBigPrefix + intToStr(menuFontNameVeryBigSize) + menuFontNameVeryBigPostfix;
|
string menuFontNameVeryBig= menuFontNameVeryBigPrefix + intToStr(menuFontNameVeryBigSize) + menuFontNameVeryBigPostfix;
|
||||||
|
|
||||||
menuFontVeryBig= renderer.newFont(rsGlobal);
|
menuFontVeryBig= renderer.newFont(rsGlobal);
|
||||||
menuFontVeryBig->setType(menuFontNameVeryBig,config.getString("FontMenuBig",""));
|
menuFontVeryBig->setType(menuFontNameVeryBig,config.getString("FontMenuVeryBig",""));
|
||||||
menuFontVeryBig->setSize(menuFontNameVeryBigSize);
|
menuFontVeryBig->setSize(menuFontNameVeryBigSize);
|
||||||
|
menuFontVeryBig->setYOffsetFactor(config.getFloat("FontMenuVeryBigYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
|
menuFontVeryBig3D= renderer.newFont3D(rsGlobal);
|
||||||
|
menuFontVeryBig3D->setType(menuFontNameVeryBig,config.getString("FontMenuVeryBig",""));
|
||||||
|
menuFontVeryBig3D->setSize(menuFontNameVeryBigSize);
|
||||||
|
menuFontVeryBig3D->setYOffsetFactor(config.getFloat("FontMenuVeryBigYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] menuFontNameVeryBig = [%s] menuFontNameVeryBigSize = %d\n",__FILE__,__FUNCTION__,__LINE__,menuFontNameVeryBig.c_str(),menuFontNameVeryBigSize);
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] menuFontNameVeryBig = [%s] menuFontNameVeryBigSize = %d\n",__FILE__,__FUNCTION__,__LINE__,menuFontNameVeryBig.c_str(),menuFontNameVeryBigSize);
|
||||||
|
|
||||||
|
@ -259,6 +296,12 @@ void CoreData::load() {
|
||||||
consoleFont= renderer.newFont(rsGlobal);
|
consoleFont= renderer.newFont(rsGlobal);
|
||||||
consoleFont->setType(consoleFontName,config.getString("FontConsole",""));
|
consoleFont->setType(consoleFontName,config.getString("FontConsole",""));
|
||||||
consoleFont->setSize(consoleFontNameSize);
|
consoleFont->setSize(consoleFontNameSize);
|
||||||
|
consoleFont->setYOffsetFactor(config.getFloat("FontConsoleYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
|
consoleFont3D= renderer.newFont3D(rsGlobal);
|
||||||
|
consoleFont3D->setType(consoleFontName,config.getString("FontConsole",""));
|
||||||
|
consoleFont3D->setSize(consoleFontNameSize);
|
||||||
|
consoleFont3D->setYOffsetFactor(config.getFloat("FontConsoleYOffsetFactor",floatToStr(FontMetrics::DEFAULT_Y_OFFSET_FACTOR).c_str()));
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] consoleFontName = [%s] consoleFontNameSize = %d\n",__FILE__,__FUNCTION__,__LINE__,consoleFontName.c_str(),consoleFontNameSize);
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] consoleFontName = [%s] consoleFontNameSize = %d\n",__FILE__,__FUNCTION__,__LINE__,consoleFontName.c_str(),consoleFontNameSize);
|
||||||
|
|
||||||
|
@ -273,6 +316,7 @@ void CoreData::load() {
|
||||||
menuMusic.open(dir+"/menu/music/menu_music.ogg");
|
menuMusic.open(dir+"/menu/music/menu_music.ogg");
|
||||||
menuMusic.setNext(&menuMusic);
|
menuMusic.setNext(&menuMusic);
|
||||||
waterSounds.resize(6);
|
waterSounds.resize(6);
|
||||||
|
|
||||||
for(int i=0; i<6; ++i){
|
for(int i=0; i<6; ++i){
|
||||||
waterSounds[i]= new StaticSound();
|
waterSounds[i]= new StaticSound();
|
||||||
waterSounds[i]->load(dir+"/water_sounds/water"+intToStr(i)+".wav");
|
waterSounds[i]->load(dir+"/water_sounds/water"+intToStr(i)+".wav");
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Glest{ namespace Game{
|
||||||
using Shared::Graphics::Texture2D;
|
using Shared::Graphics::Texture2D;
|
||||||
using Shared::Graphics::Texture3D;
|
using Shared::Graphics::Texture3D;
|
||||||
using Shared::Graphics::Font2D;
|
using Shared::Graphics::Font2D;
|
||||||
|
using Shared::Graphics::Font3D;
|
||||||
using Shared::Sound::StrSound;
|
using Shared::Sound::StrSound;
|
||||||
using Shared::Sound::StaticSound;
|
using Shared::Sound::StaticSound;
|
||||||
|
|
||||||
|
@ -67,6 +68,13 @@ private:
|
||||||
Font2D *menuFontVeryBig;
|
Font2D *menuFontVeryBig;
|
||||||
Font2D *consoleFont;
|
Font2D *consoleFont;
|
||||||
|
|
||||||
|
Font3D *displayFont3D;
|
||||||
|
Font3D *menuFontNormal3D;
|
||||||
|
Font3D *displayFontSmall3D;
|
||||||
|
Font3D *menuFontBig3D;
|
||||||
|
Font3D *menuFontVeryBig3D;
|
||||||
|
Font3D *consoleFont3D;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CoreData &getInstance();
|
static CoreData &getInstance();
|
||||||
~CoreData();
|
~CoreData();
|
||||||
|
@ -107,6 +115,13 @@ public:
|
||||||
Font2D *getMenuFontVeryBig() const {return menuFontVeryBig;}
|
Font2D *getMenuFontVeryBig() const {return menuFontVeryBig;}
|
||||||
Font2D *getConsoleFont() const {return consoleFont;}
|
Font2D *getConsoleFont() const {return consoleFont;}
|
||||||
|
|
||||||
|
Font3D *getDisplayFont3D() const {return displayFont3D;}
|
||||||
|
Font3D *getDisplayFontSmall3D() const {return displayFontSmall3D;}
|
||||||
|
Font3D *getMenuFontNormal3D() const {return menuFontNormal3D;}
|
||||||
|
Font3D *getMenuFontBig3D() const {return menuFontBig3D;}
|
||||||
|
Font3D *getMenuFontVeryBig3D() const {return menuFontVeryBig3D;}
|
||||||
|
Font3D *getConsoleFont3D() const {return consoleFont3D;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CoreData(){};
|
CoreData(){};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "platform_util.h"
|
#include "platform_util.h"
|
||||||
#include "game_constants.h"
|
#include "game_constants.h"
|
||||||
#include "game_util.h"
|
#include "game_util.h"
|
||||||
|
#include "platform_common.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -30,6 +31,11 @@ namespace Glest{ namespace Game{
|
||||||
// class Lang
|
// class Lang
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
|
Lang::Lang() {
|
||||||
|
language = "";
|
||||||
|
is_utf8_language = false;
|
||||||
|
}
|
||||||
|
|
||||||
Lang &Lang::getInstance() {
|
Lang &Lang::getInstance() {
|
||||||
static Lang lang;
|
static Lang lang;
|
||||||
return lang;
|
return lang;
|
||||||
|
@ -47,9 +53,14 @@ void Lang::loadStrings(const string &language, Properties &properties, bool file
|
||||||
if(fileMustExist == false && fileExists(languageFile) == false) {
|
if(fileMustExist == false && fileExists(languageFile) == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
is_utf8_language = valid_utf8_file(languageFile.c_str());
|
||||||
properties.load(languageFile);
|
properties.load(languageFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Lang::isUTF8Language() const {
|
||||||
|
return is_utf8_language;
|
||||||
|
}
|
||||||
|
|
||||||
void Lang::loadScenarioStrings(const string &scenarioDir, const string &scenarioName){
|
void Lang::loadScenarioStrings(const string &scenarioDir, const string &scenarioName){
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scenarioDir = [%s] scenarioName = [%s]\n",__FILE__,__FUNCTION__,__LINE__,scenarioDir.c_str(),scenarioName.c_str());
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scenarioDir = [%s] scenarioName = [%s]\n",__FILE__,__FUNCTION__,__LINE__,scenarioDir.c_str(),scenarioName.c_str());
|
||||||
|
|
||||||
|
|
|
@ -28,24 +28,30 @@ using Shared::Util::Properties;
|
||||||
class Lang {
|
class Lang {
|
||||||
private:
|
private:
|
||||||
string language;
|
string language;
|
||||||
|
bool is_utf8_language;
|
||||||
|
|
||||||
Properties strings;
|
Properties strings;
|
||||||
Properties scenarioStrings;
|
Properties scenarioStrings;
|
||||||
|
|
||||||
std::map<string,Properties> otherLanguageStrings;
|
std::map<string,Properties> otherLanguageStrings;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Lang(){};
|
Lang();
|
||||||
void loadStrings(const string &language, Properties &properties, bool fileMustExist);
|
void loadStrings(const string &language, Properties &properties, bool fileMustExist);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Lang &getInstance();
|
static Lang &getInstance();
|
||||||
|
|
||||||
void loadStrings(const string &language);
|
void loadStrings(const string &language);
|
||||||
void loadScenarioStrings(const string &scenarioDir, const string &scenarioName);
|
void loadScenarioStrings(const string &scenarioDir, const string &scenarioName);
|
||||||
|
|
||||||
string get(const string &s,string language="");
|
string get(const string &s,string language="");
|
||||||
bool hasString(const string &s, string language="");
|
bool hasString(const string &s, string language="");
|
||||||
string getScenarioString(const string &s);
|
string getScenarioString(const string &s);
|
||||||
|
|
||||||
string getLanguage() const { return language; }
|
string getLanguage() const { return language; }
|
||||||
bool isLanguageLocal(string compareLanguage) const;
|
bool isLanguageLocal(string compareLanguage) const;
|
||||||
|
bool isUTF8Language() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}//end namespace
|
}}//end namespace
|
||||||
|
|
|
@ -159,6 +159,7 @@ Renderer::Renderer() {
|
||||||
showDebugUILevel = debugui_fps;
|
showDebugUILevel = debugui_fps;
|
||||||
modelRenderer = NULL;
|
modelRenderer = NULL;
|
||||||
textRenderer = NULL;
|
textRenderer = NULL;
|
||||||
|
textRenderer3D = NULL;
|
||||||
particleRenderer = NULL;
|
particleRenderer = NULL;
|
||||||
saveScreenShotThread = NULL;
|
saveScreenShotThread = NULL;
|
||||||
mapSurfaceData.clear();
|
mapSurfaceData.clear();
|
||||||
|
@ -191,6 +192,7 @@ Renderer::Renderer() {
|
||||||
|
|
||||||
modelRenderer= graphicsFactory->newModelRenderer();
|
modelRenderer= graphicsFactory->newModelRenderer();
|
||||||
textRenderer= graphicsFactory->newTextRenderer2D();
|
textRenderer= graphicsFactory->newTextRenderer2D();
|
||||||
|
textRenderer3D = graphicsFactory->newTextRenderer3D();
|
||||||
particleRenderer= graphicsFactory->newParticleRenderer();
|
particleRenderer= graphicsFactory->newParticleRenderer();
|
||||||
|
|
||||||
//resources
|
//resources
|
||||||
|
@ -238,6 +240,8 @@ Renderer::~Renderer() {
|
||||||
modelRenderer = NULL;
|
modelRenderer = NULL;
|
||||||
delete textRenderer;
|
delete textRenderer;
|
||||||
textRenderer = NULL;
|
textRenderer = NULL;
|
||||||
|
delete textRenderer3D;
|
||||||
|
textRenderer3D = NULL;
|
||||||
delete particleRenderer;
|
delete particleRenderer;
|
||||||
particleRenderer = NULL;
|
particleRenderer = NULL;
|
||||||
|
|
||||||
|
@ -579,6 +583,10 @@ Font2D *Renderer::newFont(ResourceScope rs){
|
||||||
return fontManager[rs]->newFont2D();
|
return fontManager[rs]->newFont2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Font3D *Renderer::newFont3D(ResourceScope rs){
|
||||||
|
return fontManager[rs]->newFont3D();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs){
|
void Renderer::manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs){
|
||||||
particleManager[rs]->manage(particleSystem);
|
particleManager[rs]->manage(particleSystem);
|
||||||
}
|
}
|
||||||
|
@ -687,10 +695,12 @@ void Renderer::loadGameCameraMatrix() {
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
if(gameCamera != NULL) {
|
||||||
glRotatef(gameCamera->getVAng(), -1, 0, 0);
|
glRotatef(gameCamera->getVAng(), -1, 0, 0);
|
||||||
glRotatef(gameCamera->getHAng(), 0, 1, 0);
|
glRotatef(gameCamera->getHAng(), 0, 1, 0);
|
||||||
glTranslatef(-gameCamera->getPos().x, -gameCamera->getPos().y, -gameCamera->getPos().z);
|
glTranslatef(-gameCamera->getPos().x, -gameCamera->getPos().y, -gameCamera->getPos().z);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::loadCameraMatrix(const Camera *camera) {
|
void Renderer::loadCameraMatrix(const Camera *camera) {
|
||||||
const Vec3f &position= camera->getConstPosition();
|
const Vec3f &position= camera->getConstPosition();
|
||||||
|
@ -1229,6 +1239,42 @@ Vec2i computeCenteredPos(const string &text, Font2D *font, int x, int y) {
|
||||||
return textPos;
|
return textPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vec2i computeCenteredPos(const string &text, Font3D *font, int x, int y) {
|
||||||
|
if(font == NULL) {
|
||||||
|
throw runtime_error("font == NULL");
|
||||||
|
}
|
||||||
|
const Metrics &metrics= Metrics::getInstance();
|
||||||
|
FontMetrics *fontMetrics= font->getMetrics();
|
||||||
|
|
||||||
|
if(fontMetrics == NULL) {
|
||||||
|
throw runtime_error("fontMetrics == NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
int virtualX = (fontMetrics->getTextWidth(text) > 0 ? static_cast<int>(fontMetrics->getTextWidth(text) / 2.f) : 5);
|
||||||
|
int virtualY = (fontMetrics->getHeight() > 0 ? static_cast<int>(fontMetrics->getHeight() / 2.f) : 5);
|
||||||
|
|
||||||
|
Vec2i textPos(
|
||||||
|
x-metrics.toVirtualX(virtualX),
|
||||||
|
y-metrics.toVirtualY(virtualY));
|
||||||
|
|
||||||
|
return textPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::renderText3D(const string &text, Font3D *font, float alpha, int x, int y, bool centered) {
|
||||||
|
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glColor4fv(Vec4f(1.f, 1.f, 1.f, alpha).ptr());
|
||||||
|
|
||||||
|
Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
|
||||||
|
//Vec2i pos= Vec2i(x, y);
|
||||||
|
|
||||||
|
textRenderer3D->begin(font);
|
||||||
|
textRenderer3D->render(text, pos.x, pos.y, font->getSize());
|
||||||
|
textRenderer3D->end();
|
||||||
|
|
||||||
|
glPopAttrib();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::renderText(const string &text, Font2D *font, float alpha, int x, int y, bool centered) {
|
void Renderer::renderText(const string &text, Font2D *font, float alpha, int x, int y, bool centered) {
|
||||||
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
@ -1243,6 +1289,19 @@ void Renderer::renderText(const string &text, Font2D *font, float alpha, int x,
|
||||||
glPopAttrib();
|
glPopAttrib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::renderText3D(const string &text, Font3D *font, const Vec3f &color, int x, int y, bool centered) {
|
||||||
|
glPushAttrib(GL_CURRENT_BIT);
|
||||||
|
glColor3fv(color.ptr());
|
||||||
|
|
||||||
|
Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
|
||||||
|
|
||||||
|
textRenderer3D->begin(font);
|
||||||
|
textRenderer3D->render(text, pos.x, pos.y);
|
||||||
|
textRenderer3D->end();
|
||||||
|
|
||||||
|
glPopAttrib();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::renderText(const string &text, Font2D *font, const Vec3f &color, int x, int y, bool centered){
|
void Renderer::renderText(const string &text, Font2D *font, const Vec3f &color, int x, int y, bool centered){
|
||||||
glPushAttrib(GL_CURRENT_BIT);
|
glPushAttrib(GL_CURRENT_BIT);
|
||||||
glColor3fv(color.ptr());
|
glColor3fv(color.ptr());
|
||||||
|
@ -1256,6 +1315,20 @@ void Renderer::renderText(const string &text, Font2D *font, const Vec3f &color,
|
||||||
glPopAttrib();
|
glPopAttrib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::renderText3D(const string &text, Font3D *font, const Vec4f &color, int x, int y, bool centered) {
|
||||||
|
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glColor4fv(color.ptr());
|
||||||
|
|
||||||
|
Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
|
||||||
|
|
||||||
|
textRenderer3D->begin(font);
|
||||||
|
textRenderer3D->render(text, pos.x, pos.y);
|
||||||
|
textRenderer3D->end();
|
||||||
|
|
||||||
|
glPopAttrib();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::renderText(const string &text, Font2D *font, const Vec4f &color, int x, int y, bool centered){
|
void Renderer::renderText(const string &text, Font2D *font, const Vec4f &color, int x, int y, bool centered){
|
||||||
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
@ -1270,6 +1343,29 @@ void Renderer::renderText(const string &text, Font2D *font, const Vec4f &color,
|
||||||
glPopAttrib();
|
glPopAttrib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::renderTextShadow3D(const string &text, Font3D *font,const Vec4f &color, int x, int y, bool centered) {
|
||||||
|
if(font == NULL) {
|
||||||
|
throw runtime_error("font == NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
glPushAttrib(GL_CURRENT_BIT);
|
||||||
|
|
||||||
|
Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
|
||||||
|
|
||||||
|
textRenderer3D->begin(font);
|
||||||
|
if(color.w < 0.5) {
|
||||||
|
glColor3f(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
textRenderer3D->render(text, pos.x-1.0f, pos.y-1.0f);
|
||||||
|
}
|
||||||
|
glColor3f(color.x,color.y,color.z);
|
||||||
|
|
||||||
|
textRenderer3D->render(text, pos.x, pos.y);
|
||||||
|
textRenderer3D->end();
|
||||||
|
|
||||||
|
glPopAttrib();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::renderTextShadow(const string &text, Font2D *font,const Vec4f &color, int x, int y, bool centered){
|
void Renderer::renderTextShadow(const string &text, Font2D *font,const Vec4f &color, int x, int y, bool centered){
|
||||||
if(font == NULL) {
|
if(font == NULL) {
|
||||||
throw runtime_error("font == NULL");
|
throw runtime_error("font == NULL");
|
||||||
|
@ -1282,9 +1378,11 @@ void Renderer::renderTextShadow(const string &text, Font2D *font,const Vec4f &co
|
||||||
textRenderer->begin(font);
|
textRenderer->begin(font);
|
||||||
if(color.w < 0.5) {
|
if(color.w < 0.5) {
|
||||||
glColor3f(0.0f, 0.0f, 0.0f);
|
glColor3f(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
textRenderer->render(text, pos.x-1.0f, pos.y-1.0f);
|
textRenderer->render(text, pos.x-1.0f, pos.y-1.0f);
|
||||||
}
|
}
|
||||||
glColor3f(color.x,color.y,color.z);
|
glColor3f(color.x,color.y,color.z);
|
||||||
|
|
||||||
textRenderer->render(text, pos.x, pos.y);
|
textRenderer->render(text, pos.x, pos.y);
|
||||||
textRenderer->end();
|
textRenderer->end();
|
||||||
|
|
||||||
|
@ -1460,9 +1558,16 @@ void Renderer::renderButton(GraphicButton *button, const Vec4f *fontColorOverrid
|
||||||
Vec2i textPos= Vec2i(x+w/2, y+h/2);
|
Vec2i textPos= Vec2i(x+w/2, y+h/2);
|
||||||
|
|
||||||
if(button->getEditable()) {
|
if(button->getEditable()) {
|
||||||
|
Font2D *font = button->getFont();
|
||||||
|
//Font3D *font3d = ConvertFont2DTo3D(button->getFont());
|
||||||
renderText(
|
renderText(
|
||||||
button->getText(), button->getFont(), color,
|
button->getText(), font, color,
|
||||||
x+w/2, y+h/2, true);
|
x+w/2, y+h/2, true);
|
||||||
|
//delete font3d;
|
||||||
|
|
||||||
|
// renderText(
|
||||||
|
// button->getText(), button->getFont(), color,
|
||||||
|
// x+w/2, y+h/2, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
renderText(
|
renderText(
|
||||||
|
@ -4676,6 +4781,60 @@ void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2,
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::renderProgressBar3D(int size, int x, int y, Font3D *font, int customWidth,
|
||||||
|
string prefixLabel,bool centeredText) {
|
||||||
|
|
||||||
|
int currentSize = size;
|
||||||
|
int maxSize = maxProgressBar;
|
||||||
|
string renderText = intToStr(static_cast<int>(size)) + "%";
|
||||||
|
if(customWidth > 0) {
|
||||||
|
if(size > 0) {
|
||||||
|
currentSize = (int)((double)customWidth * ((double)size / 100.0));
|
||||||
|
}
|
||||||
|
maxSize = customWidth;
|
||||||
|
if(maxSize <= 0) {
|
||||||
|
maxSize = maxProgressBar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(prefixLabel != "") {
|
||||||
|
renderText = prefixLabel + renderText;
|
||||||
|
}
|
||||||
|
|
||||||
|
//bar
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor4fv(progressBarFront2.ptr());
|
||||||
|
glVertex2i(x, y);
|
||||||
|
glVertex2i(x, y+10);
|
||||||
|
glColor4fv(progressBarFront1.ptr());
|
||||||
|
glVertex2i(x + currentSize, y+10);
|
||||||
|
glVertex2i(x + currentSize, y);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
//transp bar
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor4fv(progressBarBack2.ptr());
|
||||||
|
glVertex2i(x + currentSize, y);
|
||||||
|
glVertex2i(x + currentSize, y+10);
|
||||||
|
glColor4fv(progressBarBack1.ptr());
|
||||||
|
glVertex2i(x + maxSize, y+10);
|
||||||
|
glVertex2i(x + maxSize, y);
|
||||||
|
glEnd();
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
//text
|
||||||
|
glColor3fv(defColor.ptr());
|
||||||
|
|
||||||
|
textRenderer3D->begin(font);
|
||||||
|
if(centeredText == true) {
|
||||||
|
textRenderer3D->render(renderText.c_str(), x + maxSize / 2, y, centeredText);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
textRenderer3D->render(renderText.c_str(), x, y, centeredText);
|
||||||
|
}
|
||||||
|
textRenderer3D->end();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::renderProgressBar(int size, int x, int y, Font2D *font, int customWidth,
|
void Renderer::renderProgressBar(int size, int x, int y, Font2D *font, int customWidth,
|
||||||
string prefixLabel,bool centeredText) {
|
string prefixLabel,bool centeredText) {
|
||||||
|
|
||||||
|
@ -4719,6 +4878,7 @@ void Renderer::renderProgressBar(int size, int x, int y, Font2D *font, int custo
|
||||||
|
|
||||||
//text
|
//text
|
||||||
glColor3fv(defColor.ptr());
|
glColor3fv(defColor.ptr());
|
||||||
|
|
||||||
textRenderer->begin(font);
|
textRenderer->begin(font);
|
||||||
if(centeredText == true) {
|
if(centeredText == true) {
|
||||||
textRenderer->render(renderText.c_str(), x + maxSize / 2, y, centeredText);
|
textRenderer->render(renderText.c_str(), x + maxSize / 2, y, centeredText);
|
||||||
|
|
|
@ -221,6 +221,7 @@ private:
|
||||||
//renderers
|
//renderers
|
||||||
ModelRenderer *modelRenderer;
|
ModelRenderer *modelRenderer;
|
||||||
TextRenderer2D *textRenderer;
|
TextRenderer2D *textRenderer;
|
||||||
|
TextRenderer3D *textRenderer3D;
|
||||||
ParticleRenderer *particleRenderer;
|
ParticleRenderer *particleRenderer;
|
||||||
|
|
||||||
//texture managers
|
//texture managers
|
||||||
|
@ -322,6 +323,8 @@ public:
|
||||||
Texture2D *newTexture2D(ResourceScope rs);
|
Texture2D *newTexture2D(ResourceScope rs);
|
||||||
Texture3D *newTexture3D(ResourceScope rs);
|
Texture3D *newTexture3D(ResourceScope rs);
|
||||||
Font2D *newFont(ResourceScope rs);
|
Font2D *newFont(ResourceScope rs);
|
||||||
|
Font3D *newFont3D(ResourceScope rs);
|
||||||
|
|
||||||
TextRenderer2D *getTextRenderer() const {return textRenderer;}
|
TextRenderer2D *getTextRenderer() const {return textRenderer;}
|
||||||
void manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs);
|
void manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs);
|
||||||
void cleanupParticleSystems(vector<ParticleSystem *> &particleSystems,ResourceScope rs);
|
void cleanupParticleSystems(vector<ParticleSystem *> &particleSystems,ResourceScope rs);
|
||||||
|
@ -352,6 +355,13 @@ public:
|
||||||
void renderText(const string &text, Font2D *font, const Vec4f &color, int x, int y, bool centered=false);
|
void renderText(const string &text, Font2D *font, const Vec4f &color, int x, int y, bool centered=false);
|
||||||
void renderTextShadow(const string &text, Font2D *font,const Vec4f &color, int x, int y, bool centered= false);
|
void renderTextShadow(const string &text, Font2D *font,const Vec4f &color, int x, int y, bool centered= false);
|
||||||
|
|
||||||
|
void renderText3D(const string &text, Font3D *font, float alpha, int x, int y, bool centered);
|
||||||
|
void renderText3D(const string &text, Font3D *font, const Vec3f &color, int x, int y, bool centered);
|
||||||
|
void renderText3D(const string &text, Font3D *font, const Vec4f &color, int x, int y, bool centered);
|
||||||
|
void renderTextShadow3D(const string &text, Font3D *font,const Vec4f &color, int x, int y, bool centered);
|
||||||
|
void renderProgressBar3D(int size, int x, int y, Font3D *font, int customWidth,
|
||||||
|
string prefixLabel,bool centeredText);
|
||||||
|
|
||||||
//components
|
//components
|
||||||
void renderLabel(GraphicLabel *label);
|
void renderLabel(GraphicLabel *label);
|
||||||
void renderLabel(GraphicLabel *label,const Vec3f *color);
|
void renderLabel(GraphicLabel *label,const Vec3f *color);
|
||||||
|
|
|
@ -125,6 +125,7 @@ const char *GAME_ARGS[] = {
|
||||||
"--disable-backtrace",
|
"--disable-backtrace",
|
||||||
"--disable-vbo",
|
"--disable-vbo",
|
||||||
"--disable-sound",
|
"--disable-sound",
|
||||||
|
"--enable-legacyfonts",
|
||||||
"--verbose"
|
"--verbose"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -159,6 +160,7 @@ enum GAME_ARG_TYPE {
|
||||||
GAME_ARG_DISABLE_BACKTRACE,
|
GAME_ARG_DISABLE_BACKTRACE,
|
||||||
GAME_ARG_DISABLE_VBO,
|
GAME_ARG_DISABLE_VBO,
|
||||||
GAME_ARG_DISABLE_SOUND,
|
GAME_ARG_DISABLE_SOUND,
|
||||||
|
GAME_ARG_ENABLE_LEGACYFONTS,
|
||||||
GAME_ARG_VERBOSE_MODE
|
GAME_ARG_VERBOSE_MODE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1059,6 +1061,8 @@ void printParameterHelp(const char *argv0, bool foundInvalidArgs) {
|
||||||
printf("\n%s\t\t\tdisables trying to use Vertex Buffer Objects.",GAME_ARGS[GAME_ARG_DISABLE_VBO]);
|
printf("\n%s\t\t\tdisables trying to use Vertex Buffer Objects.",GAME_ARGS[GAME_ARG_DISABLE_VBO]);
|
||||||
printf("\n%s\t\t\tdisables the sound system.",GAME_ARGS[GAME_ARG_DISABLE_SOUND]);
|
printf("\n%s\t\t\tdisables the sound system.",GAME_ARGS[GAME_ARG_DISABLE_SOUND]);
|
||||||
|
|
||||||
|
printf("\n%s\t\t\tenables using the legacy font system.",GAME_ARGS[GAME_ARG_ENABLE_LEGACYFONTS]);
|
||||||
|
|
||||||
printf("\n%s\t\t\tdisplays verbose information in the console.",GAME_ARGS[GAME_ARG_VERBOSE_MODE]);
|
printf("\n%s\t\t\tdisplays verbose information in the console.",GAME_ARGS[GAME_ARG_VERBOSE_MODE]);
|
||||||
|
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
|
@ -2445,6 +2449,11 @@ int glestMain(int argc, char** argv) {
|
||||||
TextureGl::setEnableATIHacks(enableATIHacks);
|
TextureGl::setEnableATIHacks(enableATIHacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(config.getBool("EnableLegacyFonts","false") == true || hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_ENABLE_LEGACYFONTS]) == true) {
|
||||||
|
Font::forceLegacyFonts = true;
|
||||||
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**WARNING** Forcing Legacy Fonts Enabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Set some statics based on ini entries
|
// Set some statics based on ini entries
|
||||||
SystemFlags::ENABLE_THREADED_LOGGING = config.getBool("ThreadedLogging","true");
|
SystemFlags::ENABLE_THREADED_LOGGING = config.getBool("ThreadedLogging","true");
|
||||||
FontGl::setDefault_fontType(config.getString("DefaultFont",FontGl::getDefault_fontType().c_str()));
|
FontGl::setDefault_fontType(config.getString("DefaultFont",FontGl::getDefault_fontType().c_str()));
|
||||||
|
@ -2573,6 +2582,10 @@ int glestMain(int argc, char** argv) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( lang.hasString("FONT_YOFFSET_FACTOR")) {
|
||||||
|
FontMetrics::DEFAULT_Y_OFFSET_FACTOR = strToFloat(lang.get("FONT_YOFFSET_FACTOR"));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
// Win32 overrides for fonts (just in case they must be different)
|
// Win32 overrides for fonts (just in case they must be different)
|
||||||
if( lang.hasString("FONT_CHARCOUNT_WINDOWS")) {
|
if( lang.hasString("FONT_CHARCOUNT_WINDOWS")) {
|
||||||
|
@ -2598,6 +2611,10 @@ int glestMain(int argc, char** argv) {
|
||||||
_putenv(newEnvValue.c_str());
|
_putenv(newEnvValue.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( lang.hasString("FONT_YOFFSET_FACTOR_WINDOWS")) {
|
||||||
|
FontMetrics::DEFAULT_Y_OFFSET_FACTOR = strToFloat(lang.get("FONT_YOFFSET_FACTOR_WINDOWS"));
|
||||||
|
}
|
||||||
|
|
||||||
// end win32
|
// end win32
|
||||||
#endif
|
#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);
|
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);
|
||||||
|
|
|
@ -110,7 +110,6 @@ void MainMenu::render(){
|
||||||
state->render();
|
state->render();
|
||||||
renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim);
|
renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim);
|
||||||
|
|
||||||
//if(config.getBool("DebugMode")){
|
|
||||||
if(renderer.getShowDebugUI() == true) {
|
if(renderer.getShowDebugUI() == true) {
|
||||||
renderer.renderText(
|
renderer.renderText(
|
||||||
"FPS: " + intToStr(lastFps),
|
"FPS: " + intToStr(lastFps),
|
||||||
|
|
|
@ -13,11 +13,12 @@
|
||||||
#define _SHARED_GRAPHICS_FONT_H_
|
#define _SHARED_GRAPHICS_FONT_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "font_text.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
class Text;
|
//class Text;
|
||||||
|
|
||||||
namespace Shared { namespace Graphics {
|
namespace Shared { namespace Graphics {
|
||||||
|
|
||||||
|
@ -26,15 +27,23 @@ namespace Shared { namespace Graphics {
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
class FontMetrics {
|
class FontMetrics {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float *widths;
|
float *widths;
|
||||||
float height;
|
float height;
|
||||||
|
|
||||||
|
float yOffsetFactor;
|
||||||
Text *textHandler;
|
Text *textHandler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static float DEFAULT_Y_OFFSET_FACTOR;
|
||||||
|
|
||||||
FontMetrics(Text *textHandler=NULL);
|
FontMetrics(Text *textHandler=NULL);
|
||||||
~FontMetrics();
|
~FontMetrics();
|
||||||
|
|
||||||
|
void setYOffsetFactor(float yOffsetFactor);
|
||||||
|
float getYOffsetFactor() const;
|
||||||
|
|
||||||
void setTextHandler(Text *textHandler);
|
void setTextHandler(Text *textHandler);
|
||||||
Text * getTextHandler();
|
Text * getTextHandler();
|
||||||
|
|
||||||
|
@ -54,6 +63,7 @@ public:
|
||||||
static int charCount;
|
static int charCount;
|
||||||
static std::string fontTypeName;
|
static std::string fontTypeName;
|
||||||
static bool fontIsMultibyte;
|
static bool fontIsMultibyte;
|
||||||
|
static bool forceLegacyFonts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Width {
|
enum Width {
|
||||||
|
@ -65,13 +75,14 @@ protected:
|
||||||
string type;
|
string type;
|
||||||
int width;
|
int width;
|
||||||
bool inited;
|
bool inited;
|
||||||
|
int size;
|
||||||
FontMetrics metrics;
|
FontMetrics metrics;
|
||||||
|
|
||||||
Text *textHandler;
|
Text *textHandler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//constructor & destructor
|
//constructor & destructor
|
||||||
Font();
|
Font(FontTextHandlerType type);
|
||||||
virtual ~Font();
|
virtual ~Font();
|
||||||
virtual void init()=0;
|
virtual void init()=0;
|
||||||
virtual void end()=0;
|
virtual void end()=0;
|
||||||
|
@ -81,10 +92,16 @@ public:
|
||||||
int getWidth() const;
|
int getWidth() const;
|
||||||
FontMetrics *getMetrics() {return &metrics;}
|
FontMetrics *getMetrics() {return &metrics;}
|
||||||
Text * getTextHandler() {return textHandler;}
|
Text * getTextHandler() {return textHandler;}
|
||||||
|
float getYOffsetFactor() const;
|
||||||
|
string getType() const;
|
||||||
|
|
||||||
//set
|
//set
|
||||||
|
void setYOffsetFactor(float yOffsetFactor);
|
||||||
void setType(string typeX11, string typeGeneric);
|
void setType(string typeX11, string typeGeneric);
|
||||||
void setWidth(int width);
|
void setWidth(int width);
|
||||||
|
|
||||||
|
int getSize() const;
|
||||||
|
void setSize(int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
@ -93,14 +110,11 @@ public:
|
||||||
|
|
||||||
class Font2D: public Font {
|
class Font2D: public Font {
|
||||||
protected:
|
protected:
|
||||||
int size;
|
//int size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Font2D();
|
Font2D(FontTextHandlerType type=ftht_2D);
|
||||||
virtual ~Font2D() {};
|
virtual ~Font2D() {};
|
||||||
|
|
||||||
int getSize() const;
|
|
||||||
void setSize(int size);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
@ -112,13 +126,15 @@ protected:
|
||||||
float depth;
|
float depth;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Font3D();
|
Font3D(FontTextHandlerType type=ftht_3D);
|
||||||
virtual ~Font3D() {};
|
virtual ~Font3D() {};
|
||||||
|
|
||||||
float getDepth() const {return depth;}
|
float getDepth() const {return depth;}
|
||||||
void setDepth(float depth) {this->depth= depth;}
|
void setDepth(float depth) {this->depth= depth;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Font3D *ConvertFont2DTo3D(Font2D *font);
|
||||||
|
|
||||||
}}//end namespace
|
}}//end namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,17 +15,25 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
enum FontTextHandlerType {
|
||||||
|
ftht_2D,
|
||||||
|
ftht_3D
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class upon which all text rendering calls are made.
|
* Base class upon which all text rendering calls are made.
|
||||||
*/
|
*/
|
||||||
//====================================================================
|
//====================================================================
|
||||||
class Text
|
class Text
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
FontTextHandlerType type;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static std::string DEFAULT_FONT_PATH;
|
static std::string DEFAULT_FONT_PATH;
|
||||||
|
|
||||||
Text();
|
Text(FontTextHandlerType type);
|
||||||
virtual ~Text();
|
virtual ~Text();
|
||||||
|
|
||||||
virtual void init(string fontName, int fontSize);
|
virtual void init(string fontName, int fontSize);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "font_text.h"
|
#include "font_text.h"
|
||||||
|
|
||||||
namespace Shared { namespace Graphics { namespace Gl {
|
namespace Shared { namespace Graphics { namespace Gl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use FTGL for rendering text in OpenGL
|
* Use FTGL for rendering text in OpenGL
|
||||||
*/
|
*/
|
||||||
|
@ -27,7 +28,7 @@ class TextFTGL : public Text
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TextFTGL();
|
TextFTGL(FontTextHandlerType type);
|
||||||
virtual ~TextFTGL();
|
virtual ~TextFTGL();
|
||||||
virtual void init(string fontName, int fontSize);
|
virtual void init(string fontName, int fontSize);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Shared { namespace Graphics { namespace Gl {
|
||||||
|
|
||||||
class Font2DGl;
|
class Font2DGl;
|
||||||
class Font3DGl;
|
class Font3DGl;
|
||||||
|
class TextRenderer3DGl;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// class TextRenderer2DGl
|
// class TextRenderer2DGl
|
||||||
|
@ -29,6 +30,9 @@ private:
|
||||||
Font2DGl *font;
|
Font2DGl *font;
|
||||||
bool rendering;
|
bool rendering;
|
||||||
|
|
||||||
|
//Font3DGl *font3D;
|
||||||
|
//TextRenderer3DGl *tester;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextRenderer2DGl();
|
TextRenderer2DGl();
|
||||||
virtual ~TextRenderer2DGl();
|
virtual ~TextRenderer2DGl();
|
||||||
|
@ -52,7 +56,7 @@ public:
|
||||||
virtual ~TextRenderer3DGl();
|
virtual ~TextRenderer3DGl();
|
||||||
|
|
||||||
virtual void begin(Font3D *font);
|
virtual void begin(Font3D *font);
|
||||||
virtual void render(const string &text, float x, float y, float size, bool centered);
|
virtual void render(const string &text, float x, float y, bool centered);
|
||||||
virtual void end();
|
virtual void end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
virtual ~TextRenderer3D(){};
|
virtual ~TextRenderer3D(){};
|
||||||
|
|
||||||
virtual void begin(Font3D *font)= 0;
|
virtual void begin(Font3D *font)= 0;
|
||||||
virtual void render(const string &text, float x, float y, float size, bool centered= false)= 0;
|
virtual void render(const string &text, float x, float y, bool centered= false)= 0;
|
||||||
virtual void end()= 0;
|
virtual void end()= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,8 @@ string getFullFileArchiveExtractCommand(string fileArchiveExtractCommand,
|
||||||
bool executeShellCommand(string cmd,int expectedResult=IGNORE_CMD_RESULT_VALUE);
|
bool executeShellCommand(string cmd,int expectedResult=IGNORE_CMD_RESULT_VALUE);
|
||||||
string executable_path(string exeName,bool includeExeNameInPath=false);
|
string executable_path(string exeName,bool includeExeNameInPath=false);
|
||||||
|
|
||||||
|
bool valid_utf8_file(const char* file_name);
|
||||||
|
|
||||||
class ValueCheckerVault {
|
class ValueCheckerVault {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
615
source/shared_lib/include/util/string_utils.h
Normal file
615
source/shared_lib/include/util/string_utils.h
Normal file
|
@ -0,0 +1,615 @@
|
||||||
|
/* TA3D, a remake of Total Annihilation
|
||||||
|
Copyright (C) 2005 Roland BROCHARD
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*/
|
||||||
|
|
||||||
|
#ifndef _SHARED_UTIL_W_STRING_H__
|
||||||
|
#define _SHARED_UTIL_W_STRING_H__
|
||||||
|
|
||||||
|
# include <sstream>
|
||||||
|
# include <list>
|
||||||
|
# include <vector>
|
||||||
|
# include <cstdarg>
|
||||||
|
# include <string>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Force the Use of the Boost functions
|
||||||
|
*/
|
||||||
|
# define TA3D_USE_BOOST 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//! \name Macros for Shared::Util::String
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Macro to append some data to the string
|
||||||
|
# define TA3D_WSTR_APPEND std::stringstream out; \
|
||||||
|
out << v; \
|
||||||
|
append(out.str());\
|
||||||
|
return *this
|
||||||
|
|
||||||
|
//! Macro to convert the string into a given type
|
||||||
|
# define TA3D_WSTR_CAST_OP(X) X v; \
|
||||||
|
fromString<X>(v, *this); \
|
||||||
|
return v;
|
||||||
|
|
||||||
|
//! Macro to append the value of a boolean (true -> "true", false -> "false")
|
||||||
|
# define TA3D_WSTR_APPEND_BOOL(X) append(X ? "true" : "false")
|
||||||
|
|
||||||
|
//@} // Macros for Shared::Util::String
|
||||||
|
|
||||||
|
|
||||||
|
# define TA3D_WSTR_SEPARATORS " \t\r\n"
|
||||||
|
|
||||||
|
using namespace Shared::Platform;
|
||||||
|
|
||||||
|
namespace Shared { namespace Util {
|
||||||
|
|
||||||
|
/*! \class String
|
||||||
|
** \brief A String implementation for `TA3D`
|
||||||
|
**
|
||||||
|
** \code
|
||||||
|
** Shared::Util::String a("abcd");
|
||||||
|
** std::cout << a << std::endl; // display: `abcd`
|
||||||
|
** Shared::Util::String b(10 + 2);
|
||||||
|
** std::cout << b << std::endl; // display: `12`
|
||||||
|
** Shared::Util::String c(10.3);
|
||||||
|
** std::cout << c << std::endl; // display: `10.3`
|
||||||
|
**
|
||||||
|
** // The same with the operator `<<`
|
||||||
|
** Shared::Util::String d;
|
||||||
|
** d << "Value : " << 42;
|
||||||
|
** std::cout << d << std::endl; // display: `Value : 42`
|
||||||
|
** \endcode
|
||||||
|
**
|
||||||
|
** Here is an example to show when to use static methods :
|
||||||
|
** \code
|
||||||
|
** Shared::Util::String s = "HelLo wOrLd";
|
||||||
|
** std::cout << Shared::Util::String::ToLower(s) << std::endl; // `hello world`
|
||||||
|
** std::cout << s << std::endl; // `HelLo wOrLd`
|
||||||
|
** std::cout << s.toLower() << std::endl; // `hello world`
|
||||||
|
** std::cout << s << std::endl; // `hello world`
|
||||||
|
** \endcode
|
||||||
|
*/
|
||||||
|
class String : public std::string
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! A String list
|
||||||
|
typedef std::list<String> List;
|
||||||
|
//! A String vector
|
||||||
|
typedef std::vector<String> Vector;
|
||||||
|
|
||||||
|
//! Char Case
|
||||||
|
enum CharCase
|
||||||
|
{
|
||||||
|
//! The string should remain untouched
|
||||||
|
soCaseSensitive,
|
||||||
|
//! The string should be converted to lowercase
|
||||||
|
soIgnoreCase
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
** \brief Copy then Convert the case (lower case) of characters in the string using the UTF8 charset
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ToLower(const char* s) {return String(s).toLower();}
|
||||||
|
/*!
|
||||||
|
** \brief Copy then Convert the case (lower case) of characters in the string using the UTF8 charset
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ToLower(const wchar_t* s) {return String(s).toLower();}
|
||||||
|
/*!
|
||||||
|
** \brief Copy then Convert the case (lower case) of characters in the string using the UTF8 charset
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ToLower(const String& s) {return String(s).toLower();}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Copy then Convert the case (upper case) of characters in the string using the UTF8 charset
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ToUpper(const char* s) {return String(s).toUpper();}
|
||||||
|
/*!
|
||||||
|
** \brief Copy then Convert the case (upper case) of characters in the string using the UTF8 charset
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ToUpper(const wchar_t* s) {return String(s).toUpper();}
|
||||||
|
/*!
|
||||||
|
** \brief Copy then Convert the case (upper case) of characters in the string using the UTF8 charset
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ToUpper(const String& s) {return String(s).toUpper();}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Remove trailing and leading spaces
|
||||||
|
** \param s The string to convert
|
||||||
|
** \param trimChars The chars to remove
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String Trim(const char* s, const String& trimChars = TA3D_WSTR_SEPARATORS) {return String(s).trim(trimChars);}
|
||||||
|
/*!
|
||||||
|
** \brief Remove trailing and leading spaces
|
||||||
|
** \param s The string to convert
|
||||||
|
** \param trimChars The chars to remove
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String Trim(const wchar_t* s, const String& trimChars = TA3D_WSTR_SEPARATORS) {return String(s).trim(trimChars);}
|
||||||
|
/*!
|
||||||
|
** \brief Remove trailing and leading spaces
|
||||||
|
** \param s The string to convert
|
||||||
|
** \param trimChars The chars to remove
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String Trim(const String& s, const String& trimChars = TA3D_WSTR_SEPARATORS) {return String(s).trim(trimChars);}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert all antislashes into slashes
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ConvertAntiSlashesIntoSlashes(const String& s) {return String(s).convertAntiSlashesIntoSlashes();}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert all slashes into antislashes
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String ConvertSlashesIntoAntiSlashes(const String& s) {return String(s).convertSlashesIntoAntiSlashes();}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Extract the key and its value from a string (mainly provided by TDF files)
|
||||||
|
**
|
||||||
|
** \param s A line (ex: ` category=core vtol ctrl_v level1 weapon notsub ;`)
|
||||||
|
** \param[out] key The key that has been found
|
||||||
|
** \param[out] value The associated value
|
||||||
|
** \param chcase The key will be converted to lowercase if equals to `soIgnoreCase`
|
||||||
|
**
|
||||||
|
** \code
|
||||||
|
** String k, v;
|
||||||
|
**
|
||||||
|
** // -> k='category'
|
||||||
|
** // -> v='core vtol ctrl_v level1 weapon notsub'
|
||||||
|
** String::ToKeyValue(" category=core vtol ctrl_v level1 weapon notsub ;", k, v)
|
||||||
|
**
|
||||||
|
** // -> k='foo'
|
||||||
|
** // -> v='bar'
|
||||||
|
** String::ToKeyValue(" foo = bar ; ");
|
||||||
|
**
|
||||||
|
** // -> k='}' v=''
|
||||||
|
** String::ToKeyValue(" } ", k, v);
|
||||||
|
**
|
||||||
|
** // -> k='[' v='Example of Section'
|
||||||
|
** String::ToKeyValue(" [Example of Section] ", k, v);
|
||||||
|
**
|
||||||
|
** // -> k='foo' v='bar'
|
||||||
|
** String::ToKeyValue(" foo=bar; // comment", k, v);
|
||||||
|
**
|
||||||
|
** // -> k='foo' v='bar'
|
||||||
|
** String::ToKeyValue(" foo=bar; // comments here; ", k, v);
|
||||||
|
** \endcode
|
||||||
|
*/
|
||||||
|
static void ToKeyValue(const String& s, String& key, String& value, const enum CharCase chcase = soCaseSensitive);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Find the index of a string in a vector
|
||||||
|
** \param l The vector
|
||||||
|
** \param s The string to look for
|
||||||
|
** \return The index of the string found, -1 otherwise
|
||||||
|
*/
|
||||||
|
static int FindInList(const String::Vector& l, const char* s);
|
||||||
|
static int FindInList(const String::Vector& l, const String& s);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert a string from ASCII to UTF8
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new Null-terminated String (must be deleted with the keyword `delete[]`), even if s is NULL
|
||||||
|
*/
|
||||||
|
static char* ConvertToUTF8(const char* s);
|
||||||
|
/*!
|
||||||
|
** \brief Convert a string from ASCII to UTF8
|
||||||
|
** \param s The string to convert
|
||||||
|
** \param len The length of the string
|
||||||
|
** \param[out] The new size
|
||||||
|
** \return A new Null-terminated String (must be deleted with the keyword `delete[]`), even if s is NULL
|
||||||
|
*/
|
||||||
|
static char* ConvertToUTF8(const char* s, const uint32 len);
|
||||||
|
static char* ConvertToUTF8(const char* s, const uint32 len, uint32& newSize);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert a string from ASCII to UTF8
|
||||||
|
** \param s The string to convert
|
||||||
|
** \return A new String
|
||||||
|
*/
|
||||||
|
static String ConvertToUTF8(const String& s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Formatted string
|
||||||
|
** \param format The format of the new string
|
||||||
|
** \return A new string
|
||||||
|
*/
|
||||||
|
static String Format(const String& f, ...);
|
||||||
|
static String Format(const char* f, ...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! \name Constructors and Destructor
|
||||||
|
//@{
|
||||||
|
//! Default constructor
|
||||||
|
String() :std::string() {}
|
||||||
|
//! Constructor by copy
|
||||||
|
String(const String& v, size_type pos = 0, size_type n = npos) :std::string(v, pos, n) {}
|
||||||
|
//! Constructor with a default value from a std::string
|
||||||
|
String(const std::string& v) :std::string(v) {}
|
||||||
|
//! Constructor with a default value from a wide string (wchar_t*)
|
||||||
|
String(const wchar_t* v) :std::string() {if (v) *this << v;}
|
||||||
|
//! Constructor with a default value from a string (char*)
|
||||||
|
String(const char* v) :std::string() { if (v) append(v); }
|
||||||
|
//! Constructor with a default value from a string (char*) and a length
|
||||||
|
String(const char* v, String::size_type n) :std::string(v, n) {}
|
||||||
|
//! Constructor with a default value from a single char
|
||||||
|
String(const char v) :std::string() {*this += v;}
|
||||||
|
//! Constructor with a default value from an int (8 bits)
|
||||||
|
String(const int8_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from an int (16 bits)
|
||||||
|
String(const int16_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from an int (32 bits)
|
||||||
|
String(const int32_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from an int (64 bits)
|
||||||
|
String(const int64_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from an unsigned int (8 bits)
|
||||||
|
String(const uint8_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from an unsigned int (16 bits)
|
||||||
|
String(const uint16_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from an unsigned int (32 bits)
|
||||||
|
String(const uint32_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from an unsigned int (64 bits)
|
||||||
|
String(const uint64_t v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from a float
|
||||||
|
String(const float v) :std::string() {*this << v;}
|
||||||
|
//! Constructor with a default value from a double
|
||||||
|
String(const double v) :std::string() {*this << v;}
|
||||||
|
//! Destructor
|
||||||
|
~String() {}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
|
||||||
|
//! \name The operator `<<`
|
||||||
|
//@{
|
||||||
|
//! Append a string (char*)
|
||||||
|
String& operator << (const char* v) {append(v);return *this;}
|
||||||
|
//! Append a string (stl)
|
||||||
|
String& operator << (const std::string& v) {append(v);return *this;}
|
||||||
|
//! Append a string (Shared::Util::String)
|
||||||
|
String& operator << (const String& v) {append(v);return *this;}
|
||||||
|
//! Append a single char
|
||||||
|
String& operator << (const char v) {*(static_cast<std::string*>(this)) += v; return *this;}
|
||||||
|
//! Append a wide string (wchar_t*)
|
||||||
|
String& operator << (const wchar_t* v);
|
||||||
|
//! Append an int (8 bits)
|
||||||
|
String& operator << (const int8_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Append an unsigned int (8 bits)
|
||||||
|
String& operator << (const uint8_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Append an int (16 bits)
|
||||||
|
String& operator << (const int16_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Append an unsigned int (16 bits)
|
||||||
|
String& operator << (const uint16_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Append an int (32 bits)
|
||||||
|
String& operator << (const int32_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Append an unsigned int (32 bits)
|
||||||
|
String& operator << (const uint32_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Append an int (64 bits)
|
||||||
|
String& operator << (const int64_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Append an unsigned int (64 bits)
|
||||||
|
String& operator << (const uint64_t v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Convert then Append a float
|
||||||
|
String& operator << (const float v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Convert then Append a double
|
||||||
|
String& operator << (const double v) {TA3D_WSTR_APPEND;}
|
||||||
|
//! Convert then Append a boolean (will be converted into "true" or "false")
|
||||||
|
String& operator << (const bool v) {TA3D_WSTR_APPEND_BOOL(v);return *this;}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
|
||||||
|
//! \name Convertions
|
||||||
|
//@{
|
||||||
|
//! Convert this string into an int (8 bits)
|
||||||
|
int8_t toInt8() const {TA3D_WSTR_CAST_OP(int8_t);}
|
||||||
|
//! Convert this string into an int (16 bits)
|
||||||
|
int16_t toInt16() const {TA3D_WSTR_CAST_OP(int16_t);}
|
||||||
|
//! Convert this string into an int (32 bits)
|
||||||
|
int32_t toInt32() const {TA3D_WSTR_CAST_OP(int32_t);}
|
||||||
|
//! Convert this string into an int (64 bits)
|
||||||
|
int64_t toInt64() const {TA3D_WSTR_CAST_OP(int64_t);}
|
||||||
|
//! Convert this string into an unsigned int (8 bits)
|
||||||
|
uint8_t toUInt8() const {TA3D_WSTR_CAST_OP(uint8_t);}
|
||||||
|
//! Convert this string into an unsigned int (16 bits)
|
||||||
|
uint16_t toUInt16() const {TA3D_WSTR_CAST_OP(uint16_t);}
|
||||||
|
//! Convert this string into an unsigned int (32 bits)
|
||||||
|
uint32_t toUInt32() const {TA3D_WSTR_CAST_OP(uint32_t);}
|
||||||
|
//! Convert this string into an unsigned int (64 bits)
|
||||||
|
uint64_t toUInt64() const {TA3D_WSTR_CAST_OP(uint64_t);}
|
||||||
|
//! Convert this string into a float
|
||||||
|
float toFloat() const {TA3D_WSTR_CAST_OP(float);}
|
||||||
|
//! Convert this string into a float with a default value if empty
|
||||||
|
float toFloat(const float def) const {if (empty()) return def;TA3D_WSTR_CAST_OP(float);}
|
||||||
|
//! Convert this string into a double
|
||||||
|
double toDouble() const {TA3D_WSTR_CAST_OP(double);}
|
||||||
|
//! Convert this string into a bool (true if the lower case value is equals to "true", "1" or "on")
|
||||||
|
bool toBool() const;
|
||||||
|
|
||||||
|
//! \name The operator `+=` (with the same abilities than the operator `<<`)
|
||||||
|
//@{
|
||||||
|
//! Append a string (char*)
|
||||||
|
String& operator += (const char* v) {append(v); return *this;}
|
||||||
|
//! Append a string (stl)
|
||||||
|
String& operator += (const std::string& v) {append(v); return *this;}
|
||||||
|
//! Append a string (Shared::Util::String)
|
||||||
|
String& operator += (const Shared::Util::String& v) {append(v); return *this; }
|
||||||
|
//! Append a single char
|
||||||
|
String& operator += (const char v) {*(static_cast<std::string*>(this)) += (char)v; return *this;}
|
||||||
|
//! Append a wide string (wchar_t*)
|
||||||
|
String& operator += (const wchar_t* v) {*this << v; return *this;}
|
||||||
|
//! Append an int (8 bits)
|
||||||
|
String& operator += (const int8_t v) {*this << v; return *this;}
|
||||||
|
//! Append an unsigned int (8 bits)
|
||||||
|
String& operator += (const uint8_t v) {*this << v; return *this;}
|
||||||
|
//! Append an int (16 bits)
|
||||||
|
String& operator += (const int16_t v) {*this << v; return *this; }
|
||||||
|
//! Append an unsigned int (16 bits)
|
||||||
|
String& operator += (const uint16_t v) {*this << v; return *this; }
|
||||||
|
//! Append an int (32 bits)
|
||||||
|
String& operator += (const int32_t v) {*this << v; return *this; }
|
||||||
|
//! Append an unsigned int (32 bits)
|
||||||
|
String& operator += (const uint32_t v) {*this << v; return *this; }
|
||||||
|
//! Append an int (64 bits)
|
||||||
|
String& operator += (const int64_t v) {*this << v; return *this; }
|
||||||
|
//! Append an unsigned int (64 bits)
|
||||||
|
String& operator += (const uint64_t v) {*this << v; return *this; }
|
||||||
|
//! Convert then Append a float
|
||||||
|
String& operator += (const float v) {*this << v; return *this; }
|
||||||
|
//! Convert then Append a double
|
||||||
|
String& operator += (const double v) {*this << v; return *this; }
|
||||||
|
//! Convert then Append a boolean (will be converted into "true" or "false")
|
||||||
|
String& operator += (const bool v) {TA3D_WSTR_APPEND_BOOL(v); return *this; }
|
||||||
|
//@}
|
||||||
|
|
||||||
|
|
||||||
|
//! \name The operator `+`
|
||||||
|
//@{
|
||||||
|
//! Create a new String from the concatenation of *this and a string
|
||||||
|
const String operator + (const String& rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a char
|
||||||
|
const String operator + (const char rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a widechar
|
||||||
|
const String operator + (const wchar_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a const char*
|
||||||
|
const String operator + (const char* rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a wide string
|
||||||
|
const String operator + (const wchar_t* rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a signed int (8 bits)
|
||||||
|
const String operator + (const int8_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a signed int (16 bits)
|
||||||
|
const String operator + (const int16_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a signed int (32 bits)
|
||||||
|
const String operator + (const int32_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a signed int (64 bits)
|
||||||
|
const String operator + (const int64_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and an unsigned int (8 bits)
|
||||||
|
const String operator + (const uint8_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and an unsigned int (16 bits)
|
||||||
|
const String operator + (const uint16_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and an unsigned int (32 bits)
|
||||||
|
const String operator + (const uint32_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and an unsigned int (64 bits)
|
||||||
|
const String operator + (const uint64_t rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a float
|
||||||
|
const String operator + (const float rhs) { return String(*this) += rhs; }
|
||||||
|
//! Create a new String from the concatenation of *this and a double
|
||||||
|
const String operator + (const double rhs) { return String(*this) += rhs; }
|
||||||
|
//@}
|
||||||
|
|
||||||
|
|
||||||
|
//! \name Case convertion
|
||||||
|
//@{
|
||||||
|
/*!
|
||||||
|
** \brief Convert the case (lower case) of characters in the string using the UTF8 charset
|
||||||
|
** \return Returns *this
|
||||||
|
*/
|
||||||
|
String& toLower();
|
||||||
|
/*!
|
||||||
|
** \brief Convert the case (upper case) of characters in the string using the UTF8 charset
|
||||||
|
** \return Returns *this
|
||||||
|
*/
|
||||||
|
String& toUpper();
|
||||||
|
//@} Case convertion
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Remove trailing and leading spaces
|
||||||
|
** \param trimChars The chars to remove
|
||||||
|
** \return Returns *this
|
||||||
|
*/
|
||||||
|
String& trim(const String& trimChars = TA3D_WSTR_SEPARATORS);
|
||||||
|
|
||||||
|
|
||||||
|
//! \name Split
|
||||||
|
//@{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Divide a string into several parts
|
||||||
|
** \param[out] All found parts
|
||||||
|
** \param sepearators Sequence of chars considered as a separator
|
||||||
|
** \param emptyBefore True to clear the vector before fulfill it
|
||||||
|
** \warning Do not take care of string representation (with `'` or `"`)
|
||||||
|
*/
|
||||||
|
void split(String::Vector& out, const String& separators = TA3D_WSTR_SEPARATORS, const bool emptyBefore = true) const;
|
||||||
|
/*!
|
||||||
|
** \brief Divide a string into several parts
|
||||||
|
** \param[out] All found parts
|
||||||
|
** \param sepearators Sequence of chars considered as a separator
|
||||||
|
** \param emptyBefore True to clear the list before fulfill it
|
||||||
|
** \warning Do not take care of string representation (with `'` or `"`)
|
||||||
|
*/
|
||||||
|
void split(String::List& out, const String& separators = TA3D_WSTR_SEPARATORS, const bool emptyBefore = true) const;
|
||||||
|
|
||||||
|
//@} Split
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Extract the key and its value from a string (mainly provided by TDF files)
|
||||||
|
**
|
||||||
|
** \param[out] key The key that has been found
|
||||||
|
** \param[out] value The associated value
|
||||||
|
**
|
||||||
|
** \see String::ToKeyValue()
|
||||||
|
*/
|
||||||
|
void toKeyValue(String& key, String& value, const enum CharCase chcase = soCaseSensitive) const
|
||||||
|
{ToKeyValue(*this, key, value, chcase);}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert all antislashes into slashes
|
||||||
|
** \return Returns *this
|
||||||
|
*/
|
||||||
|
String& convertAntiSlashesIntoSlashes();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert all slashes into antislashes
|
||||||
|
** \return Returns *this
|
||||||
|
*/
|
||||||
|
String& convertSlashesIntoAntiSlashes();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Get the hash value of this string
|
||||||
|
*/
|
||||||
|
uint32 hashValue() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert the string from ASCII to UTF8
|
||||||
|
** \return Always *this
|
||||||
|
*/
|
||||||
|
String& convertToUTF8() {*this = ConvertToUTF8(*this); return *this;}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Replace a substr by another one
|
||||||
|
** \param toSearch The string to look for
|
||||||
|
** \param replaceWith The string replacement
|
||||||
|
** \param option Option when looking for the string `toSearch`
|
||||||
|
** \return Always *this
|
||||||
|
*/
|
||||||
|
String& findAndReplace(const String& toSearch, const String& replaceWith, const enum String::CharCase option = soCaseSensitive);
|
||||||
|
String& findAndReplace(char toSearch, const char replaceWith, const enum String::CharCase option = soCaseSensitive);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Reset the current value with a formatted string
|
||||||
|
** \param f The format of the new string
|
||||||
|
** \return Always *this
|
||||||
|
*/
|
||||||
|
String& format(const String& f, ...);
|
||||||
|
String& format(const char* f, ...);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Append a formatted string
|
||||||
|
** \param f The format of the new string
|
||||||
|
** \return Always *this
|
||||||
|
*/
|
||||||
|
String& appendFormat(const String& f, ...);
|
||||||
|
String& appendFormat(const char* f, ...);
|
||||||
|
String& vappendFormat(const char* f, va_list parg);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Detect if the string matches the given pattern
|
||||||
|
** \param pattern
|
||||||
|
** \return true if match
|
||||||
|
*/
|
||||||
|
bool match(const String &pattern);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief returns a substring assuming current string is an UTF8 String
|
||||||
|
** \param pos
|
||||||
|
** \param len
|
||||||
|
** \return the substring
|
||||||
|
*/
|
||||||
|
String substrUTF8(int pos = 0, int len = -1) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief returns the String size assuming it's in UTF8
|
||||||
|
** \return the number of UTF8 symbols
|
||||||
|
*/
|
||||||
|
int sizeUTF8() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
** \brief Convert a string into another type, given by the template parameter `T`
|
||||||
|
** \param[out] t The destination variable
|
||||||
|
** \param s The string to convert
|
||||||
|
** \param f The base to use for the convertion (std::hex, std::dec, ...)
|
||||||
|
** \return True if the operation succeeded, False otherwise
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
bool fromString(T& t, const String& s) const
|
||||||
|
{
|
||||||
|
std::istringstream iss(s);
|
||||||
|
if (s.size() > 2)
|
||||||
|
{
|
||||||
|
if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
|
||||||
|
iss >> std::hex;
|
||||||
|
else if (s[0] == '0' && s[1] != 'x' && s[1] != 'X')
|
||||||
|
iss >> std::oct;
|
||||||
|
else
|
||||||
|
iss >> std::dec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
iss >> std::dec;
|
||||||
|
return !(iss >> t).fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ASCIItoUTF8(const byte c, byte *out);
|
||||||
|
}; // class String
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//int ASCIItoUTF8(const byte c, byte *out);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
** \brief Convert an UTF-8 String into a WideChar String
|
||||||
|
** \todo This class must be removed as soon as possible and is only here to prevent against
|
||||||
|
** stange bugs with the previous implementation
|
||||||
|
*/
|
||||||
|
struct WString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WString(const char* s);
|
||||||
|
WString(const String& str);
|
||||||
|
|
||||||
|
void fromUtf8(const char* s, size_t length);
|
||||||
|
const wchar_t* cw_str() const {return pBuffer;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wchar_t pBuffer[5120];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}} // namespace TA3D
|
||||||
|
|
||||||
|
#endif // _SHARED_UTIL_W_STRING_H__
|
34
source/shared_lib/include/util/utf8.h
Normal file
34
source/shared_lib/include/util/utf8.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2006 Nemanja Trifunovic
|
||||||
|
|
||||||
|
/*
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
|
||||||
|
#include "utf8/checked.h"
|
||||||
|
#include "utf8/unchecked.h"
|
||||||
|
|
||||||
|
#endif // header guard
|
327
source/shared_lib/include/util/utf8/checked.h
Normal file
327
source/shared_lib/include/util/utf8/checked.h
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
// Copyright 2006 Nemanja Trifunovic
|
||||||
|
|
||||||
|
/*
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace utf8
|
||||||
|
{
|
||||||
|
// Base for the exceptions that may be thrown from the library
|
||||||
|
class exception : public std::exception {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Exceptions that may be thrown from the library functions.
|
||||||
|
class invalid_code_point : public exception {
|
||||||
|
uint32_t cp;
|
||||||
|
public:
|
||||||
|
invalid_code_point(uint32_t cp) : cp(cp) {}
|
||||||
|
virtual const char* what() const throw() { return "Invalid code point"; }
|
||||||
|
uint32_t code_point() const {return cp;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class invalid_utf8 : public exception {
|
||||||
|
uint8_t u8;
|
||||||
|
public:
|
||||||
|
invalid_utf8 (uint8_t u) : u8(u) {}
|
||||||
|
virtual const char* what() const throw() { return "Invalid UTF-8"; }
|
||||||
|
uint8_t utf8_octet() const {return u8;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class invalid_utf16 : public exception {
|
||||||
|
uint16_t u16;
|
||||||
|
public:
|
||||||
|
invalid_utf16 (uint16_t u) : u16(u) {}
|
||||||
|
virtual const char* what() const throw() { return "Invalid UTF-16"; }
|
||||||
|
uint16_t utf16_word() const {return u16;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class not_enough_room : public exception {
|
||||||
|
public:
|
||||||
|
virtual const char* what() const throw() { return "Not enough space"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The library API - functions intended to be called by the users
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename output_iterator>
|
||||||
|
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
|
||||||
|
{
|
||||||
|
while (start != end) {
|
||||||
|
octet_iterator sequence_start = start;
|
||||||
|
internal::utf_error err_code = internal::validate_next(start, end);
|
||||||
|
switch (err_code) {
|
||||||
|
case internal::UTF8_OK :
|
||||||
|
for (octet_iterator it = sequence_start; it != start; ++it)
|
||||||
|
*out++ = *it;
|
||||||
|
break;
|
||||||
|
case internal::NOT_ENOUGH_ROOM:
|
||||||
|
throw not_enough_room();
|
||||||
|
case internal::INVALID_LEAD:
|
||||||
|
append (replacement, out);
|
||||||
|
++start;
|
||||||
|
break;
|
||||||
|
case internal::INCOMPLETE_SEQUENCE:
|
||||||
|
case internal::OVERLONG_SEQUENCE:
|
||||||
|
case internal::INVALID_CODE_POINT:
|
||||||
|
append (replacement, out);
|
||||||
|
++start;
|
||||||
|
// just one replacement mark for the sequence
|
||||||
|
while (internal::is_trail(*start) && start != end)
|
||||||
|
++start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename output_iterator>
|
||||||
|
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
|
||||||
|
{
|
||||||
|
static const uint32_t replacement_marker = internal::mask16(0xfffd);
|
||||||
|
return replace_invalid(start, end, out, replacement_marker);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||||
|
{
|
||||||
|
if (!internal::is_code_point_valid(cp))
|
||||||
|
throw invalid_code_point(cp);
|
||||||
|
|
||||||
|
if (cp < 0x80) // one octet
|
||||||
|
*(result++) = static_cast<uint8_t>(cp);
|
||||||
|
else if (cp < 0x800) { // two octets
|
||||||
|
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||||
|
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
else if (cp < 0x10000) { // three octets
|
||||||
|
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||||
|
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||||
|
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
else { // four octets
|
||||||
|
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||||
|
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
|
||||||
|
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||||
|
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
uint32_t next(octet_iterator& it, octet_iterator end)
|
||||||
|
{
|
||||||
|
uint32_t cp = 0;
|
||||||
|
internal::utf_error err_code = internal::validate_next(it, end, &cp);
|
||||||
|
switch (err_code) {
|
||||||
|
case internal::UTF8_OK :
|
||||||
|
break;
|
||||||
|
case internal::NOT_ENOUGH_ROOM :
|
||||||
|
throw not_enough_room();
|
||||||
|
case internal::INVALID_LEAD :
|
||||||
|
case internal::INCOMPLETE_SEQUENCE :
|
||||||
|
case internal::OVERLONG_SEQUENCE :
|
||||||
|
throw invalid_utf8(*it);
|
||||||
|
case internal::INVALID_CODE_POINT :
|
||||||
|
throw invalid_code_point(cp);
|
||||||
|
}
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
uint32_t peek_next(octet_iterator it, octet_iterator end)
|
||||||
|
{
|
||||||
|
return next(it, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
uint32_t prior(octet_iterator& it, octet_iterator start)
|
||||||
|
{
|
||||||
|
// can't do much if it == start
|
||||||
|
if (it == start)
|
||||||
|
throw not_enough_room();
|
||||||
|
|
||||||
|
octet_iterator end = it;
|
||||||
|
// Go back until we hit either a lead octet or start
|
||||||
|
while (internal::is_trail(*(--it)))
|
||||||
|
if (it == start)
|
||||||
|
throw invalid_utf8(*it); // error - no lead byte in the sequence
|
||||||
|
return peek_next(it, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deprecated in versions that include "prior"
|
||||||
|
template <typename octet_iterator>
|
||||||
|
uint32_t previous(octet_iterator& it, octet_iterator pass_start)
|
||||||
|
{
|
||||||
|
octet_iterator end = it;
|
||||||
|
while (internal::is_trail(*(--it)))
|
||||||
|
if (it == pass_start)
|
||||||
|
throw invalid_utf8(*it); // error - no lead byte in the sequence
|
||||||
|
octet_iterator temp = it;
|
||||||
|
return next(temp, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename distance_type>
|
||||||
|
void advance (octet_iterator& it, distance_type n, octet_iterator end)
|
||||||
|
{
|
||||||
|
for (distance_type i = 0; i < n; ++i)
|
||||||
|
next(it, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
typename std::iterator_traits<octet_iterator>::difference_type
|
||||||
|
distance (octet_iterator first, octet_iterator last)
|
||||||
|
{
|
||||||
|
typename std::iterator_traits<octet_iterator>::difference_type dist;
|
||||||
|
for (dist = 0; first < last; ++dist)
|
||||||
|
next(first, last);
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u16bit_iterator, typename octet_iterator>
|
||||||
|
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||||
|
{
|
||||||
|
while (start != end) {
|
||||||
|
uint32_t cp = internal::mask16(*start++);
|
||||||
|
// Take care of surrogate pairs first
|
||||||
|
if (internal::is_lead_surrogate(cp)) {
|
||||||
|
if (start != end) {
|
||||||
|
uint32_t trail_surrogate = internal::mask16(*start++);
|
||||||
|
if (internal::is_trail_surrogate(trail_surrogate))
|
||||||
|
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||||
|
else
|
||||||
|
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||||
|
|
||||||
|
}
|
||||||
|
// Lone trail surrogate
|
||||||
|
else if (internal::is_trail_surrogate(cp))
|
||||||
|
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||||
|
|
||||||
|
result = append(cp, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u16bit_iterator, typename octet_iterator>
|
||||||
|
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||||
|
{
|
||||||
|
while (start != end) {
|
||||||
|
uint32_t cp = next(start, end);
|
||||||
|
if (cp > 0xffff) { //make a surrogate pair
|
||||||
|
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||||
|
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*result++ = static_cast<uint16_t>(cp);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename u32bit_iterator>
|
||||||
|
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||||
|
{
|
||||||
|
while (start != end)
|
||||||
|
result = append(*(start++), result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename u32bit_iterator>
|
||||||
|
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||||
|
{
|
||||||
|
while (start != end)
|
||||||
|
(*result++) = next(start, end);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The iterator class
|
||||||
|
template <typename octet_iterator>
|
||||||
|
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||||
|
octet_iterator it;
|
||||||
|
octet_iterator range_start;
|
||||||
|
octet_iterator range_end;
|
||||||
|
public:
|
||||||
|
iterator () {};
|
||||||
|
explicit iterator (const octet_iterator& octet_it,
|
||||||
|
const octet_iterator& range_start,
|
||||||
|
const octet_iterator& range_end) :
|
||||||
|
it(octet_it), range_start(range_start), range_end(range_end)
|
||||||
|
{
|
||||||
|
if (it < range_start || it > range_end)
|
||||||
|
throw std::out_of_range("Invalid utf-8 iterator position");
|
||||||
|
}
|
||||||
|
// the default "big three" are OK
|
||||||
|
octet_iterator base () const { return it; }
|
||||||
|
uint32_t operator * () const
|
||||||
|
{
|
||||||
|
octet_iterator temp = it;
|
||||||
|
return next(temp, range_end);
|
||||||
|
}
|
||||||
|
bool operator == (const iterator& rhs) const
|
||||||
|
{
|
||||||
|
if (range_start != rhs.range_start || range_end != rhs.range_end)
|
||||||
|
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
|
||||||
|
return (it == rhs.it);
|
||||||
|
}
|
||||||
|
bool operator != (const iterator& rhs) const
|
||||||
|
{
|
||||||
|
return !(operator == (rhs));
|
||||||
|
}
|
||||||
|
iterator& operator ++ ()
|
||||||
|
{
|
||||||
|
next(it, range_end);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
iterator operator ++ (int)
|
||||||
|
{
|
||||||
|
iterator temp = *this;
|
||||||
|
next(it, range_end);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
iterator& operator -- ()
|
||||||
|
{
|
||||||
|
prior(it, range_start);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
iterator operator -- (int)
|
||||||
|
{
|
||||||
|
iterator temp = *this;
|
||||||
|
prior(it, range_start);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}; // class iterator
|
||||||
|
|
||||||
|
} // namespace utf8
|
||||||
|
|
||||||
|
#endif //header guard
|
||||||
|
|
||||||
|
|
358
source/shared_lib/include/util/utf8/core.h
Executable file
358
source/shared_lib/include/util/utf8/core.h
Executable file
|
@ -0,0 +1,358 @@
|
||||||
|
// Copyright 2006 Nemanja Trifunovic
|
||||||
|
|
||||||
|
/*
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace utf8
|
||||||
|
{
|
||||||
|
// The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
|
||||||
|
// You may need to change them to match your system.
|
||||||
|
// These typedefs have the same names as ones from cstdint, or boost/cstdint
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
|
||||||
|
// Helper code - not intended to be directly called by the library users. May be changed at any time
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
// Unicode constants
|
||||||
|
// Leading (high) surrogates: 0xd800 - 0xdbff
|
||||||
|
// Trailing (low) surrogates: 0xdc00 - 0xdfff
|
||||||
|
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
|
||||||
|
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
|
||||||
|
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
|
||||||
|
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
|
||||||
|
const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
|
||||||
|
const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
|
||||||
|
|
||||||
|
// Maximum valid value for a Unicode code point
|
||||||
|
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
|
||||||
|
|
||||||
|
template<typename octet_type>
|
||||||
|
inline uint8_t mask8(octet_type oc)
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(0xff & oc);
|
||||||
|
}
|
||||||
|
template<typename u16_type>
|
||||||
|
inline uint16_t mask16(u16_type oc)
|
||||||
|
{
|
||||||
|
return static_cast<uint16_t>(0xffff & oc);
|
||||||
|
}
|
||||||
|
template<typename octet_type>
|
||||||
|
inline bool is_trail(octet_type oc)
|
||||||
|
{
|
||||||
|
return ((mask8(oc) >> 6) == 0x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u16>
|
||||||
|
inline bool is_lead_surrogate(u16 cp)
|
||||||
|
{
|
||||||
|
return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u16>
|
||||||
|
inline bool is_trail_surrogate(u16 cp)
|
||||||
|
{
|
||||||
|
return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u16>
|
||||||
|
inline bool is_surrogate(u16 cp)
|
||||||
|
{
|
||||||
|
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u32>
|
||||||
|
inline bool is_code_point_valid(u32 cp)
|
||||||
|
{
|
||||||
|
return (cp <= CODE_POINT_MAX && !is_surrogate(cp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
inline typename std::iterator_traits<octet_iterator>::difference_type
|
||||||
|
sequence_length(octet_iterator lead_it)
|
||||||
|
{
|
||||||
|
uint8_t lead = mask8(*lead_it);
|
||||||
|
if (lead < 0x80)
|
||||||
|
return 1;
|
||||||
|
else if ((lead >> 5) == 0x6)
|
||||||
|
return 2;
|
||||||
|
else if ((lead >> 4) == 0xe)
|
||||||
|
return 3;
|
||||||
|
else if ((lead >> 3) == 0x1e)
|
||||||
|
return 4;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_difference_type>
|
||||||
|
inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
|
||||||
|
{
|
||||||
|
if (cp < 0x80) {
|
||||||
|
if (length != 1)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (cp < 0x800) {
|
||||||
|
if (length != 2)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (cp < 0x10000) {
|
||||||
|
if (length != 3)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
|
||||||
|
|
||||||
|
/// get_sequence_x functions decode utf-8 sequences of the length x
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t* code_point)
|
||||||
|
{
|
||||||
|
if (it != end) {
|
||||||
|
if (code_point)
|
||||||
|
*code_point = mask8(*it);
|
||||||
|
return UTF8_OK;
|
||||||
|
}
|
||||||
|
return NOT_ENOUGH_ROOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t* code_point)
|
||||||
|
{
|
||||||
|
utf_error ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
|
||||||
|
if (it != end) {
|
||||||
|
uint32_t cp = mask8(*it);
|
||||||
|
if (++it != end) {
|
||||||
|
if (is_trail(*it)) {
|
||||||
|
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
|
||||||
|
|
||||||
|
if (code_point)
|
||||||
|
*code_point = cp;
|
||||||
|
ret_code = UTF8_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = INCOMPLETE_SEQUENCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t* code_point)
|
||||||
|
{
|
||||||
|
utf_error ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
|
||||||
|
if (it != end) {
|
||||||
|
uint32_t cp = mask8(*it);
|
||||||
|
if (++it != end) {
|
||||||
|
if (is_trail(*it)) {
|
||||||
|
cp = ((cp << 12) & 0xffff) + ((mask8(*it) << 6) & 0xfff);
|
||||||
|
if (++it != end) {
|
||||||
|
if (is_trail(*it)) {
|
||||||
|
cp += (*it) & 0x3f;
|
||||||
|
|
||||||
|
if (code_point)
|
||||||
|
*code_point = cp;
|
||||||
|
ret_code = UTF8_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = INCOMPLETE_SEQUENCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = INCOMPLETE_SEQUENCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t* code_point)
|
||||||
|
{
|
||||||
|
utf_error ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
|
||||||
|
if (it != end) {
|
||||||
|
uint32_t cp = mask8(*it);
|
||||||
|
if (++it != end) {
|
||||||
|
if (is_trail(*it)) {
|
||||||
|
cp = ((cp << 18) & 0x1fffff) + ((mask8(*it) << 12) & 0x3ffff);
|
||||||
|
if (++it != end) {
|
||||||
|
if (is_trail(*it)) {
|
||||||
|
cp += (mask8(*it) << 6) & 0xfff;
|
||||||
|
if (++it != end) {
|
||||||
|
if (is_trail(*it)) {
|
||||||
|
cp += (*it) & 0x3f;
|
||||||
|
|
||||||
|
if (code_point)
|
||||||
|
*code_point = cp;
|
||||||
|
ret_code = UTF8_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = INCOMPLETE_SEQUENCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = INCOMPLETE_SEQUENCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = INCOMPLETE_SEQUENCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret_code = NOT_ENOUGH_ROOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t* code_point)
|
||||||
|
{
|
||||||
|
// Save the original value of it so we can go back in case of failure
|
||||||
|
// Of course, it does not make much sense with i.e. stream iterators
|
||||||
|
octet_iterator original_it = it;
|
||||||
|
|
||||||
|
uint32_t cp = 0;
|
||||||
|
// Determine the sequence length based on the lead octet
|
||||||
|
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
|
||||||
|
octet_difference_type length = sequence_length(it);
|
||||||
|
if (length == 0)
|
||||||
|
return INVALID_LEAD;
|
||||||
|
|
||||||
|
// Now that we have a valid sequence length, get trail octets and calculate the code point
|
||||||
|
utf_error err = UTF8_OK;
|
||||||
|
switch (length) {
|
||||||
|
case 1:
|
||||||
|
err = get_sequence_1(it, end, &cp);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
err = get_sequence_2(it, end, &cp);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
err = get_sequence_3(it, end, &cp);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
err = get_sequence_4(it, end, &cp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == UTF8_OK) {
|
||||||
|
// Decoding succeeded. Now, security checks...
|
||||||
|
if (is_code_point_valid(cp)) {
|
||||||
|
if (!is_overlong_sequence(cp, length)){
|
||||||
|
// Passed! Return here.
|
||||||
|
if (code_point)
|
||||||
|
*code_point = cp;
|
||||||
|
++it;
|
||||||
|
return UTF8_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = OVERLONG_SEQUENCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = INVALID_CODE_POINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failure branch - restore the original value of the iterator
|
||||||
|
it = original_it;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
|
||||||
|
return validate_next(it, end, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
/// The library API - functions intended to be called by the users
|
||||||
|
|
||||||
|
// Byte order mark
|
||||||
|
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
|
||||||
|
{
|
||||||
|
octet_iterator result = start;
|
||||||
|
while (result != end) {
|
||||||
|
internal::utf_error err_code = internal::validate_next(result, end);
|
||||||
|
if (err_code != internal::UTF8_OK)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
inline bool is_valid(octet_iterator start, octet_iterator end)
|
||||||
|
{
|
||||||
|
return (find_invalid(start, end) == end);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
inline bool starts_with_bom (octet_iterator it, octet_iterator end)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
((it != end) && (internal::mask8(*it++)) == bom[0]) &&
|
||||||
|
((it != end) && (internal::mask8(*it++)) == bom[1]) &&
|
||||||
|
((it != end) && (internal::mask8(*it)) == bom[2])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Deprecated in release 2.3
|
||||||
|
template <typename octet_iterator>
|
||||||
|
inline bool is_bom (octet_iterator it)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(internal::mask8(*it++)) == bom[0] &&
|
||||||
|
(internal::mask8(*it++)) == bom[1] &&
|
||||||
|
(internal::mask8(*it)) == bom[2]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} // namespace utf8
|
||||||
|
|
||||||
|
#endif // header guard
|
||||||
|
|
||||||
|
|
228
source/shared_lib/include/util/utf8/unchecked.h
Executable file
228
source/shared_lib/include/util/utf8/unchecked.h
Executable file
|
@ -0,0 +1,228 @@
|
||||||
|
// Copyright 2006 Nemanja Trifunovic
|
||||||
|
|
||||||
|
/*
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
namespace utf8
|
||||||
|
{
|
||||||
|
namespace unchecked
|
||||||
|
{
|
||||||
|
template <typename octet_iterator>
|
||||||
|
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||||
|
{
|
||||||
|
if (cp < 0x80) // one octet
|
||||||
|
*(result++) = static_cast<uint8_t>(cp);
|
||||||
|
else if (cp < 0x800) { // two octets
|
||||||
|
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||||
|
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
else if (cp < 0x10000) { // three octets
|
||||||
|
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||||
|
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||||
|
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
else { // four octets
|
||||||
|
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||||
|
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
|
||||||
|
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||||
|
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
uint32_t next(octet_iterator& it)
|
||||||
|
{
|
||||||
|
uint32_t cp = internal::mask8(*it);
|
||||||
|
typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
|
||||||
|
switch (length) {
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
it++;
|
||||||
|
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
++it;
|
||||||
|
cp = ((cp << 12) & 0xffff) + ((internal::mask8(*it) << 6) & 0xfff);
|
||||||
|
++it;
|
||||||
|
cp += (*it) & 0x3f;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
++it;
|
||||||
|
cp = ((cp << 18) & 0x1fffff) + ((internal::mask8(*it) << 12) & 0x3ffff);
|
||||||
|
++it;
|
||||||
|
cp += (internal::mask8(*it) << 6) & 0xfff;
|
||||||
|
++it;
|
||||||
|
cp += (*it) & 0x3f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
uint32_t peek_next(octet_iterator it)
|
||||||
|
{
|
||||||
|
return next(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
uint32_t prior(octet_iterator& it)
|
||||||
|
{
|
||||||
|
while (internal::is_trail(*(--it))) ;
|
||||||
|
octet_iterator temp = it;
|
||||||
|
return next(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
|
||||||
|
template <typename octet_iterator>
|
||||||
|
inline uint32_t previous(octet_iterator& it)
|
||||||
|
{
|
||||||
|
return prior(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename distance_type>
|
||||||
|
void advance (octet_iterator& it, distance_type n)
|
||||||
|
{
|
||||||
|
for (distance_type i = 0; i < n; ++i)
|
||||||
|
next(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator>
|
||||||
|
typename std::iterator_traits<octet_iterator>::difference_type
|
||||||
|
distance (octet_iterator first, octet_iterator last)
|
||||||
|
{
|
||||||
|
typename std::iterator_traits<octet_iterator>::difference_type dist;
|
||||||
|
for (dist = 0; first < last; ++dist)
|
||||||
|
next(first);
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u16bit_iterator, typename octet_iterator>
|
||||||
|
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||||
|
{
|
||||||
|
while (start != end) {
|
||||||
|
uint32_t cp = internal::mask16(*start++);
|
||||||
|
// Take care of surrogate pairs first
|
||||||
|
if (internal::is_lead_surrogate(cp)) {
|
||||||
|
uint32_t trail_surrogate = internal::mask16(*start++);
|
||||||
|
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||||
|
}
|
||||||
|
result = append(cp, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename u16bit_iterator, typename octet_iterator>
|
||||||
|
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||||
|
{
|
||||||
|
while (start < end) {
|
||||||
|
uint32_t cp = next(start);
|
||||||
|
if (cp > 0xffff) { //make a surrogate pair
|
||||||
|
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||||
|
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*result++ = static_cast<uint16_t>(cp);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename u32bit_iterator>
|
||||||
|
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||||
|
{
|
||||||
|
while (start != end)
|
||||||
|
result = append(*(start++), result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename octet_iterator, typename u32bit_iterator>
|
||||||
|
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||||
|
{
|
||||||
|
while (start < end)
|
||||||
|
(*result++) = next(start);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The iterator class
|
||||||
|
template <typename octet_iterator>
|
||||||
|
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||||
|
octet_iterator it;
|
||||||
|
public:
|
||||||
|
iterator () {};
|
||||||
|
explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
|
||||||
|
// the default "big three" are OK
|
||||||
|
octet_iterator base () const { return it; }
|
||||||
|
uint32_t operator * () const
|
||||||
|
{
|
||||||
|
octet_iterator temp = it;
|
||||||
|
return next(temp);
|
||||||
|
}
|
||||||
|
bool operator == (const iterator& rhs) const
|
||||||
|
{
|
||||||
|
return (it == rhs.it);
|
||||||
|
}
|
||||||
|
bool operator != (const iterator& rhs) const
|
||||||
|
{
|
||||||
|
return !(operator == (rhs));
|
||||||
|
}
|
||||||
|
iterator& operator ++ ()
|
||||||
|
{
|
||||||
|
std::advance(it, internal::sequence_length(it));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
iterator operator ++ (int)
|
||||||
|
{
|
||||||
|
iterator temp = *this;
|
||||||
|
std::advance(it, internal::sequence_length(it));
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
iterator& operator -- ()
|
||||||
|
{
|
||||||
|
prior(it);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
iterator operator -- (int)
|
||||||
|
{
|
||||||
|
iterator temp = *this;
|
||||||
|
prior(it);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}; // class iterator
|
||||||
|
|
||||||
|
} // namespace utf8::unchecked
|
||||||
|
} // namespace utf8
|
||||||
|
|
||||||
|
|
||||||
|
#endif // header guard
|
||||||
|
|
|
@ -13,16 +13,17 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "conversion.h"
|
#include "conversion.h"
|
||||||
|
|
||||||
#include "font_text.h"
|
|
||||||
#ifdef USE_FTGL
|
#ifdef USE_FTGL
|
||||||
|
|
||||||
#include "font_textFTGL.h"
|
#include "font_textFTGL.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
//#include "string_utils.h"
|
|
||||||
using namespace Shared::Util;
|
using namespace Shared::Util;
|
||||||
using namespace Shared::Graphics::Gl;
|
using namespace Shared::Graphics::Gl;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -34,6 +35,8 @@ namespace Shared { namespace Graphics {
|
||||||
int Font::charCount = 256;
|
int Font::charCount = 256;
|
||||||
std::string Font::fontTypeName = "Times New Roman";
|
std::string Font::fontTypeName = "Times New Roman";
|
||||||
bool Font::fontIsMultibyte = false;
|
bool Font::fontIsMultibyte = false;
|
||||||
|
bool Font::forceLegacyFonts = false;
|
||||||
|
float FontMetrics::DEFAULT_Y_OFFSET_FACTOR = 8.0f;
|
||||||
//
|
//
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
@ -44,6 +47,7 @@ FontMetrics::FontMetrics(Text *textHandler) {
|
||||||
this->textHandler = textHandler;
|
this->textHandler = textHandler;
|
||||||
this->widths = new float[Font::charCount];
|
this->widths = new float[Font::charCount];
|
||||||
this->height = 0;
|
this->height = 0;
|
||||||
|
this->yOffsetFactor = FontMetrics::DEFAULT_Y_OFFSET_FACTOR;
|
||||||
|
|
||||||
for(int i=0; i < Font::charCount; ++i) {
|
for(int i=0; i < Font::charCount; ++i) {
|
||||||
widths[i]= 0;
|
widths[i]= 0;
|
||||||
|
@ -55,6 +59,14 @@ FontMetrics::~FontMetrics() {
|
||||||
widths = NULL;
|
widths = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FontMetrics::setYOffsetFactor(float yOffsetFactor) {
|
||||||
|
this->yOffsetFactor = yOffsetFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FontMetrics::getYOffsetFactor() const {
|
||||||
|
return this->yOffsetFactor;
|
||||||
|
}
|
||||||
|
|
||||||
void FontMetrics::setTextHandler(Text *textHandler) {
|
void FontMetrics::setTextHandler(Text *textHandler) {
|
||||||
this->textHandler = textHandler;
|
this->textHandler = textHandler;
|
||||||
}
|
}
|
||||||
|
@ -100,15 +112,27 @@ float FontMetrics::getHeight() const {
|
||||||
// class Font
|
// class Font
|
||||||
// ===============================================
|
// ===============================================
|
||||||
|
|
||||||
Font::Font() {
|
Font::Font(FontTextHandlerType type) {
|
||||||
inited = false;
|
inited = false;
|
||||||
type = fontTypeName;
|
this->type = fontTypeName;
|
||||||
width = 400;
|
width = 400;
|
||||||
|
size = 10;
|
||||||
textHandler = NULL;
|
textHandler = NULL;
|
||||||
|
|
||||||
#ifdef USE_FTGL
|
#ifdef USE_FTGL
|
||||||
textHandler = new TextFTGL();
|
|
||||||
|
if(Font::forceLegacyFonts == false) {
|
||||||
|
try {
|
||||||
|
textHandler = NULL;
|
||||||
|
textHandler = new TextFTGL(type);
|
||||||
metrics.setTextHandler(this->textHandler);
|
metrics.setTextHandler(this->textHandler);
|
||||||
|
}
|
||||||
|
catch(exception &ex) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
||||||
|
textHandler = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,12 +143,32 @@ Font::~Font() {
|
||||||
textHandler = NULL;
|
textHandler = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Font::setYOffsetFactor(float yOffsetFactor) {
|
||||||
|
metrics.setYOffsetFactor(yOffsetFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Font::getYOffsetFactor() const {
|
||||||
|
return metrics.getYOffsetFactor();
|
||||||
|
}
|
||||||
|
|
||||||
|
string Font::getType() const {
|
||||||
|
return this->type;
|
||||||
|
}
|
||||||
|
|
||||||
void Font::setType(string typeX11, string typeGeneric) {
|
void Font::setType(string typeX11, string typeGeneric) {
|
||||||
if(textHandler) {
|
if(textHandler) {
|
||||||
|
try {
|
||||||
|
this->type= typeGeneric;
|
||||||
textHandler->init(typeGeneric,textHandler->GetFaceSize());
|
textHandler->init(typeGeneric,textHandler->GetFaceSize());
|
||||||
|
metrics.setTextHandler(this->textHandler);
|
||||||
}
|
}
|
||||||
else {
|
catch(exception &ex) {
|
||||||
this->type= type;
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
||||||
|
textHandler = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(textHandler == NULL) {
|
||||||
|
this->type= typeX11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,15 +180,7 @@ int Font::getWidth() const {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===============================================
|
int Font::getSize() const {
|
||||||
// class Font2D
|
|
||||||
// ===============================================
|
|
||||||
|
|
||||||
Font2D::Font2D() {
|
|
||||||
size = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Font2D::getSize() const {
|
|
||||||
if(textHandler) {
|
if(textHandler) {
|
||||||
return textHandler->GetFaceSize();
|
return textHandler->GetFaceSize();
|
||||||
}
|
}
|
||||||
|
@ -152,7 +188,7 @@ int Font2D::getSize() const {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Font2D::setSize(int size) {
|
void Font::setSize(int size) {
|
||||||
if(textHandler) {
|
if(textHandler) {
|
||||||
return textHandler->SetFaceSize(size);
|
return textHandler->SetFaceSize(size);
|
||||||
}
|
}
|
||||||
|
@ -161,11 +197,18 @@ void Font2D::setSize(int size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===============================================
|
||||||
|
// class Font2D
|
||||||
|
// ===============================================
|
||||||
|
|
||||||
|
Font2D::Font2D(FontTextHandlerType type) : Font(type) {
|
||||||
|
}
|
||||||
|
|
||||||
// ===============================================
|
// ===============================================
|
||||||
// class Font3D
|
// class Font3D
|
||||||
// ===============================================
|
// ===============================================
|
||||||
|
|
||||||
Font3D::Font3D() {
|
Font3D::Font3D(FontTextHandlerType type) : Font(type) {
|
||||||
depth= 10.f;
|
depth= 10.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,9 @@ using namespace std;
|
||||||
std::string Text::DEFAULT_FONT_PATH = "";
|
std::string Text::DEFAULT_FONT_PATH = "";
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
Text::Text() {}
|
Text::Text(FontTextHandlerType type) {
|
||||||
|
this->type = type;
|
||||||
|
}
|
||||||
Text::~Text() {}
|
Text::~Text() {}
|
||||||
void Text::init(string fontName, int fontSize) {}
|
void Text::init(string fontName, int fontSize) {}
|
||||||
void Text::Render(const char*, const int) {}
|
void Text::Render(const char*, const int) {}
|
||||||
|
|
|
@ -79,3 +79,19 @@ void Font3DGl::end() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}}}//end namespace
|
}}}//end namespace
|
||||||
|
|
||||||
|
namespace Shared { namespace Graphics {
|
||||||
|
|
||||||
|
using namespace Gl;
|
||||||
|
Font3D * ConvertFont2DTo3D(Font2D *font) {
|
||||||
|
|
||||||
|
Font3D *result = new Font3DGl();
|
||||||
|
result->setSize(font->getSize());
|
||||||
|
result->setType("",font->getType());
|
||||||
|
result->setYOffsetFactor(font->getYOffsetFactor());
|
||||||
|
result->setWidth(font->getWidth());
|
||||||
|
result->init();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
|
@ -33,8 +33,7 @@ namespace Shared{ namespace Graphics{ namespace Gl{
|
||||||
|
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
TextFTGL::TextFTGL() {
|
TextFTGL::TextFTGL(FontTextHandlerType type) : Text(type) {
|
||||||
|
|
||||||
|
|
||||||
//setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",0);
|
//setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",0);
|
||||||
//setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/arphic/uming.ttc",0); // Chinese
|
//setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/arphic/uming.ttc",0); // Chinese
|
||||||
|
@ -56,7 +55,17 @@ TextFTGL::TextFTGL() {
|
||||||
//ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
//ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
||||||
|
|
||||||
//ftFont = new FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
//ftFont = new FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
||||||
|
if(type == ftht_2D) {
|
||||||
ftFont = new FTGLPixmapFont(fontFile);
|
ftFont = new FTGLPixmapFont(fontFile);
|
||||||
|
//printf("2D font [%s]\n",fontFile);
|
||||||
|
}
|
||||||
|
else if(type == ftht_3D) {
|
||||||
|
ftFont = new FTBufferFont(fontFile);
|
||||||
|
//printf("3D font [%s]\n",fontFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw runtime_error("font render type not set to a known value!");
|
||||||
|
}
|
||||||
|
|
||||||
if(ftFont->Error()) {
|
if(ftFont->Error()) {
|
||||||
printf("FTGL: error loading font: %s\n", fontFile);
|
printf("FTGL: error loading font: %s\n", fontFile);
|
||||||
|
@ -96,7 +105,17 @@ void TextFTGL::init(string fontName, int fontSize) {
|
||||||
//ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
//ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
||||||
//ftFont = new FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
//ftFont = new FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
||||||
|
|
||||||
|
if(type == ftht_2D) {
|
||||||
ftFont = new FTGLPixmapFont(fontFile);
|
ftFont = new FTGLPixmapFont(fontFile);
|
||||||
|
//printf("2D font [%s]\n",fontFile);
|
||||||
|
}
|
||||||
|
else if(type == ftht_3D) {
|
||||||
|
ftFont = new FTBufferFont(fontFile);
|
||||||
|
//printf("3D font [%s]\n",fontFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw runtime_error("font render type not set to a known value!");
|
||||||
|
}
|
||||||
|
|
||||||
if(ftFont->Error()) {
|
if(ftFont->Error()) {
|
||||||
printf("FTGL: error loading font: %s\n", fontFile);
|
printf("FTGL: error loading font: %s\n", fontFile);
|
||||||
|
|
|
@ -28,16 +28,33 @@ namespace Shared { namespace Graphics { namespace Gl {
|
||||||
TextRenderer2DGl::TextRenderer2DGl() {
|
TextRenderer2DGl::TextRenderer2DGl() {
|
||||||
rendering= false;
|
rendering= false;
|
||||||
this->font = NULL;
|
this->font = NULL;
|
||||||
|
|
||||||
|
//font3D = NULL;
|
||||||
|
//tester = new TextRenderer3DGl();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextRenderer2DGl::~TextRenderer2DGl() {
|
TextRenderer2DGl::~TextRenderer2DGl() {
|
||||||
|
//delete font3D;
|
||||||
|
//font3D = NULL;
|
||||||
|
|
||||||
|
//delete tester;
|
||||||
|
//tester = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer2DGl::begin(Font2D *font) {
|
void TextRenderer2DGl::begin(Font2D *font) {
|
||||||
assert(!rendering);
|
|
||||||
|
|
||||||
rendering = true;
|
|
||||||
this->font = static_cast<Font2DGl*>(font);
|
this->font = static_cast<Font2DGl*>(font);
|
||||||
|
|
||||||
|
// if(font3D == NULL) {
|
||||||
|
// font3D = new Font3DGl();
|
||||||
|
// font3D->setYOffsetFactor(this->font->getYOffsetFactor());
|
||||||
|
// font3D->setType("", this->font->getType());
|
||||||
|
// font3D->setDepth(this->font->getWidth());
|
||||||
|
// }
|
||||||
|
// tester->begin(font3D);
|
||||||
|
// return;
|
||||||
|
|
||||||
|
assert(!rendering);
|
||||||
|
rendering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a narrow string to a wide string//
|
// Convert a narrow string to a wide string//
|
||||||
|
@ -56,6 +73,9 @@ void TextRenderer2DGl::begin(Font2D *font) {
|
||||||
// Widen an individual character
|
// Widen an individual character
|
||||||
|
|
||||||
void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, Vec3f *color) {
|
void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, Vec3f *color) {
|
||||||
|
//tester->render(text, x, y, this->font->getWidth(),centered);
|
||||||
|
//return;
|
||||||
|
|
||||||
assert(rendering);
|
assert(rendering);
|
||||||
|
|
||||||
assertGl();
|
assertGl();
|
||||||
|
@ -76,11 +96,11 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V
|
||||||
if(font->getTextHandler() != NULL) {
|
if(font->getTextHandler() != NULL) {
|
||||||
if(centered) {
|
if(centered) {
|
||||||
rasterPos.x= x - font->getTextHandler()->Advance(text.c_str()) / 2.f;
|
rasterPos.x= x - font->getTextHandler()->Advance(text.c_str()) / 2.f;
|
||||||
rasterPos.y= y + font->getTextHandler()->LineHeight(text.c_str()) / 2.f;
|
rasterPos.y= y + font->getTextHandler()->LineHeight(text.c_str()) / font->getYOffsetFactor();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rasterPos= Vec2f(static_cast<float>(x), static_cast<float>(y));
|
rasterPos= Vec2f(static_cast<float>(x), static_cast<float>(y));
|
||||||
rasterPos.y= y + (font->getTextHandler()->LineHeight(text.c_str()) / 8.f);
|
rasterPos.y= y + (font->getTextHandler()->LineHeight(text.c_str()) / font->getYOffsetFactor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -96,6 +116,9 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V
|
||||||
}
|
}
|
||||||
glRasterPos2f(rasterPos.x, rasterPos.y);
|
glRasterPos2f(rasterPos.x, rasterPos.y);
|
||||||
|
|
||||||
|
//font->getTextHandler()->Render("Zurück");
|
||||||
|
//return;
|
||||||
|
|
||||||
if(Font::fontIsMultibyte == true) {
|
if(Font::fontIsMultibyte == true) {
|
||||||
if(font->getTextHandler() != NULL) {
|
if(font->getTextHandler() != NULL) {
|
||||||
//String str("資料");
|
//String str("資料");
|
||||||
|
@ -143,12 +166,9 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V
|
||||||
|
|
||||||
//fontFTGL->Render("testování slovanský jazyk"); // Czech Works!
|
//fontFTGL->Render("testování slovanský jazyk"); // Czech Works!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This works
|
// This works
|
||||||
//fontFTGL->Render(text.c_str());
|
//fontFTGL->Render(text.c_str());
|
||||||
|
|
||||||
|
|
||||||
if(text.find("\n") == text.npos && text.find("\t") == text.npos) {
|
if(text.find("\n") == text.npos && text.find("\t") == text.npos) {
|
||||||
font->getTextHandler()->Render(text.c_str());
|
font->getTextHandler()->Render(text.c_str());
|
||||||
}
|
}
|
||||||
|
@ -311,6 +331,9 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer2DGl::end() {
|
void TextRenderer2DGl::end() {
|
||||||
|
//tester->end();
|
||||||
|
//return;
|
||||||
|
|
||||||
assert(rendering);
|
assert(rendering);
|
||||||
rendering= false;
|
rendering= false;
|
||||||
}
|
}
|
||||||
|
@ -341,7 +364,7 @@ void TextRenderer3DGl::begin(Font3D *font) {
|
||||||
assertGl();
|
assertGl();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer3DGl::render(const string &text, float x, float y, float size, bool centered) {
|
void TextRenderer3DGl::render(const string &text, float x, float y, bool centered) {
|
||||||
assert(rendering);
|
assert(rendering);
|
||||||
|
|
||||||
const unsigned char *utext= NULL;
|
const unsigned char *utext= NULL;
|
||||||
|
@ -350,13 +373,17 @@ void TextRenderer3DGl::render(const string &text, float x, float y, float size,
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glPushAttrib(GL_POLYGON_BIT);
|
glPushAttrib(GL_POLYGON_BIT);
|
||||||
float scale= size / 10.f;
|
|
||||||
|
int size = font->getSize();
|
||||||
|
//float scale= size / 15.f;
|
||||||
|
float scale= 1.0f;
|
||||||
|
//float scale= size;
|
||||||
Vec3f translatePos;
|
Vec3f translatePos;
|
||||||
|
|
||||||
if(font->getTextHandler() != NULL) {
|
if(font->getTextHandler() != NULL) {
|
||||||
if(centered) {
|
if(centered) {
|
||||||
translatePos.x = x - scale * font->getTextHandler()->Advance(text.c_str()) / 2.f;
|
translatePos.x = x - scale * font->getTextHandler()->Advance(text.c_str()) / 2.f;
|
||||||
translatePos.y = y - scale * font->getTextHandler()->LineHeight(text.c_str()) / 2.f;
|
translatePos.y = y - scale * font->getTextHandler()->LineHeight(text.c_str()) / font->getYOffsetFactor();
|
||||||
translatePos.z = 0;
|
translatePos.z = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -382,9 +409,12 @@ void TextRenderer3DGl::render(const string &text, float x, float y, float size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//glScalef(scale, scale, scale);
|
||||||
glTranslatef(translatePos.x, translatePos.y, translatePos.z);
|
glTranslatef(translatePos.x, translatePos.y, translatePos.z);
|
||||||
glScalef(scale, scale, scale);
|
|
||||||
|
|
||||||
|
font->getTextHandler()->Render(text.c_str());
|
||||||
|
|
||||||
|
/*
|
||||||
if(Font::fontIsMultibyte == true) {
|
if(Font::fontIsMultibyte == true) {
|
||||||
if(font->getTextHandler() != NULL) {
|
if(font->getTextHandler() != NULL) {
|
||||||
if(text.find("\n") == text.npos && text.find("\t") == text.npos) {
|
if(text.find("\n") == text.npos && text.find("\t") == text.npos) {
|
||||||
|
@ -532,6 +562,8 @@ void TextRenderer3DGl::render(const string &text, float x, float y, float size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
glPopAttrib();
|
glPopAttrib();
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "randomgen.h"
|
#include "randomgen.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "platform_util.h"
|
#include "platform_util.h"
|
||||||
|
#include "utf8.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using namespace Shared::Platform;
|
using namespace Shared::Platform;
|
||||||
|
@ -1934,6 +1935,33 @@ void copyFileTo(string fromFileName, string toFileName) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool valid_utf8_file(const char* file_name) {
|
||||||
|
#if defined(WIN32) && !defined(__MINGW32__)
|
||||||
|
wstring wstr = utf8_decode(file_name);
|
||||||
|
FILE *fp = _wfopen(wstr.c_str(), L"r");
|
||||||
|
ifstream ifs(fp);
|
||||||
|
#else
|
||||||
|
ifstream ifs(file_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ifs) {
|
||||||
|
return false; // even better, throw here
|
||||||
|
}
|
||||||
|
istreambuf_iterator<char> it(ifs.rdbuf());
|
||||||
|
istreambuf_iterator<char> eos;
|
||||||
|
|
||||||
|
bool result = utf8::is_valid(it, eos);
|
||||||
|
|
||||||
|
ifs.close();
|
||||||
|
#if defined(WIN32) && !defined(__MINGW32__)
|
||||||
|
if(fp) {
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// =====================================
|
// =====================================
|
||||||
// ModeInfo
|
// ModeInfo
|
||||||
// =====================================
|
// =====================================
|
||||||
|
|
|
@ -41,12 +41,15 @@ void createGlFontBitmaps(uint32 &base, const string &type, int size, int width,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("About to try font [%s]\n",type.c_str());
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("About to try font [%s]\n",type.c_str());
|
||||||
|
printf("About to try font [%s]\n",type.c_str());
|
||||||
|
|
||||||
XFontStruct* fontInfo = XLoadQueryFont(display, type.c_str());
|
XFontStruct* fontInfo = XLoadQueryFont(display, type.c_str());
|
||||||
if(fontInfo == NULL) {
|
if(fontInfo == NULL) {
|
||||||
string default_font = FontGl::getDefault_fontType();
|
string default_font = FontGl::getDefault_fontType();
|
||||||
|
|
||||||
//throw std::runtime_error("Font not found: [" + type + "]");
|
//throw std::runtime_error("Font not found: [" + type + "]");
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugError,"Font not found [%s] trying to fallback to [%s]\n",type.c_str(),default_font.c_str());
|
SystemFlags::OutputDebug(SystemFlags::debugError,"Font not found [%s] trying to fallback to [%s]\n",type.c_str(),default_font.c_str());
|
||||||
|
printf("Font not found [%s] trying to fallback to [%s]\n",type.c_str(),default_font.c_str());
|
||||||
|
|
||||||
fontInfo = XLoadQueryFont(display, default_font.c_str());
|
fontInfo = XLoadQueryFont(display, default_font.c_str());
|
||||||
if(fontInfo == NULL) {
|
if(fontInfo == NULL) {
|
||||||
|
|
|
@ -25,11 +25,21 @@
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "utf8.h"
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
//#include <locale>
|
||||||
|
//#include <iostream>
|
||||||
|
//#include <string>
|
||||||
|
//#include <sstream>
|
||||||
|
#include "string_utils.h"
|
||||||
|
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Shared::PlatformCommon;
|
using namespace Shared::PlatformCommon;
|
||||||
using namespace Shared::Platform;
|
using namespace Shared::Platform;
|
||||||
|
using namespace Shared::Graphics;
|
||||||
|
|
||||||
namespace Shared{ namespace Util{
|
namespace Shared{ namespace Util{
|
||||||
|
|
||||||
|
@ -39,37 +49,324 @@ string Properties::applicationPath = "";
|
||||||
// class Properties
|
// class Properties
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
|
//wstring widen( const string& str )
|
||||||
|
//{
|
||||||
|
// wostringstream wstm ;
|
||||||
|
// wstm.imbue(std::locale("en_US.UTF-8"));
|
||||||
|
// const ctype<wchar_t>& ctfacet =
|
||||||
|
// use_facet< ctype<wchar_t> >( wstm.getloc() ) ;
|
||||||
|
// for( size_t i=0 ; i<str.size() ; ++i )
|
||||||
|
// wstm << ctfacet.widen( str[i] ) ;
|
||||||
|
// return wstm.str() ;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
//wstring fromUtf8(const char* str, size_t length) {
|
||||||
|
// wchar_t result[4097]= L"";
|
||||||
|
// int len = 0;
|
||||||
|
// for(int i = 0 ; i < length; i++)
|
||||||
|
// {
|
||||||
|
// if (((byte)str[i]) < 0x80)
|
||||||
|
// {
|
||||||
|
// result[len++] = ((byte)str[i]);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if (((byte)str[i]) >= 0xC0)
|
||||||
|
// {
|
||||||
|
// wchar_t c = ((byte)str[i++]) - 0xC0;
|
||||||
|
// while(((byte)str[i]) >= 0x80)
|
||||||
|
// c = (c << 6) | (((byte)str[i++]) - 0x80);
|
||||||
|
// --i;
|
||||||
|
// result[len++] = c;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// result[len] = 0;
|
||||||
|
// return result;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//string conv_utf8_iso8859_7(string s) {
|
||||||
|
// int len = s.size();
|
||||||
|
// string out = "";
|
||||||
|
// string curr_char = "";
|
||||||
|
// for(int i=0; i < len; i++) {
|
||||||
|
// curr_char = curr_char + s[i];
|
||||||
|
// if( ( (s[i]) & (128+64) ) == 128) {
|
||||||
|
// //character end found
|
||||||
|
// if ( curr_char.size() == 2) {
|
||||||
|
// // 2-byte character check for it is greek one and convert
|
||||||
|
// if ((curr_char[0])==205) out = out + (char)(curr_char[1]+16);
|
||||||
|
// else if ((curr_char[0])==206) out = out + (char)(curr_char[1]+48);
|
||||||
|
// else if ((curr_char[0])==207) out = out + (char)(curr_char[1]+112);
|
||||||
|
// else ; // non greek 2-byte character, discard character
|
||||||
|
// } else ;// n-byte character, n>2, discard character
|
||||||
|
// curr_char = "";
|
||||||
|
// }
|
||||||
|
// else if ((s[i]) < 128) {
|
||||||
|
// // character is one byte (ascii)
|
||||||
|
// out = out + curr_char;
|
||||||
|
// curr_char = "";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return out;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Map from the most-significant 6 bits of the first byte to the total number of bytes in a
|
||||||
|
// UTF-8 character.
|
||||||
|
//static char UTF8_2_ISO_8859_1_len[] =
|
||||||
|
//{
|
||||||
|
// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* erroneous */
|
||||||
|
// 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//static char UTF8_2_ISO_8859_1_mask[] = {0x3F, 0x7F, 0x1F, 0x0F, 0x07,
|
||||||
|
//0x03, 0x01};
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
-------
|
||||||
|
Convert a UTF-8 string to a ISO-8859-1 MultiByte string.
|
||||||
|
No more than 'count' bytes will be written to the output buffer.
|
||||||
|
Return the size of the converted string in bytes, excl null
|
||||||
|
terminator.
|
||||||
|
*/
|
||||||
|
//int ldap_x_utf8s_to_iso_8859_1s( char *mbstr, const char *utf8str, size_t count )
|
||||||
|
//{
|
||||||
|
// int res = 0;
|
||||||
|
//
|
||||||
|
// while (*utf8str != '\0')
|
||||||
|
// {
|
||||||
|
// int len = UTF8_2_ISO_8859_1_len[(*utf8str >> 2) & 0x3F];
|
||||||
|
// unsigned long u = *utf8str & UTF8_2_ISO_8859_1_mask[len];
|
||||||
|
//
|
||||||
|
// // erroneous
|
||||||
|
// if (len == 0)
|
||||||
|
// len = 5;
|
||||||
|
//
|
||||||
|
// for (++utf8str; --len > 0 && (*utf8str != '\0'); ++utf8str)
|
||||||
|
// {
|
||||||
|
// // be sure this is not an unexpected start of a new character
|
||||||
|
// if ((*utf8str & 0xC0) != 0x80)
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// u = (u << 6) | (*utf8str & 0x3F);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (mbstr != 0 && count != 0)
|
||||||
|
// {
|
||||||
|
// // be sure there is enough space left in the destination buffer
|
||||||
|
// if (res >= count)
|
||||||
|
// return res;
|
||||||
|
//
|
||||||
|
// // add the mapped character to the destination string or '?'(0x1A, SUB) if character
|
||||||
|
// // can't be represented in ISO-8859-1
|
||||||
|
// *mbstr++ = (u <= 0xFF ? (char)u : '?');
|
||||||
|
// }
|
||||||
|
// ++res;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // add the terminating null character
|
||||||
|
// if (mbstr != 0 && count != 0)
|
||||||
|
// {
|
||||||
|
// // be sure there is enough space left in the destination buffer
|
||||||
|
// if (res >= count)
|
||||||
|
// return res;
|
||||||
|
// *mbstr = 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return res;
|
||||||
|
//} // ldap_x_utf8s_to_iso_8859_1s
|
||||||
|
//
|
||||||
|
//
|
||||||
|
///*----------------------------------------------------------------------
|
||||||
|
//-------
|
||||||
|
// Convert a ISO-8859-1 MultiByte string to a UTF-8 string.
|
||||||
|
// No more than 'count' bytes will be written to the output buffer.
|
||||||
|
// Return the size of the converted string in bytes, excl null
|
||||||
|
//terminator.
|
||||||
|
//*/
|
||||||
|
//int ldap_x_iso_8859_1s_to_utf8s(char *utf8str, const char *mbstr, size_t count)
|
||||||
|
//{
|
||||||
|
// int res = 0;
|
||||||
|
//
|
||||||
|
// // loop until we reach the end of the mb string
|
||||||
|
// for (; *mbstr != '\0'; ++mbstr)
|
||||||
|
// {
|
||||||
|
// // the character needs no mapping if the highest bit is not set
|
||||||
|
// if ((*mbstr & 0x80) == 0)
|
||||||
|
// {
|
||||||
|
// if (utf8str != 0 && count != 0)
|
||||||
|
// {
|
||||||
|
// // be sure there is enough space left in the destination buffer
|
||||||
|
// if (res >= count)
|
||||||
|
// return res;
|
||||||
|
//
|
||||||
|
// *utf8str++ = *mbstr;
|
||||||
|
// }
|
||||||
|
// ++res;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // otherwise mapping is necessary
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if (utf8str != 0 && count != 0)
|
||||||
|
// {
|
||||||
|
// // be sure there is enough space left in the destination buffer
|
||||||
|
// if (res+1 >= count)
|
||||||
|
// return res;
|
||||||
|
//
|
||||||
|
// *utf8str++ = (0xC0 | (0x03 & (*mbstr >> 6)));
|
||||||
|
// *utf8str++ = (0x80 | (0x3F & *mbstr));
|
||||||
|
// }
|
||||||
|
// res += 2;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // add the terminating null character
|
||||||
|
// if (utf8str != 0 && count != 0)
|
||||||
|
// {
|
||||||
|
// // be sure there is enough space left in the destination buffer
|
||||||
|
// if (res >= count)
|
||||||
|
// return res;
|
||||||
|
// *utf8str = 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return res;
|
||||||
|
//} // ldap_x_iso_8859_1s_to_utf8s
|
||||||
|
|
||||||
void Properties::load(const string &path, bool clearCurrentProperties) {
|
void Properties::load(const string &path, bool clearCurrentProperties) {
|
||||||
|
|
||||||
|
//wchar_t lineBuffer[maxLine]=L"";
|
||||||
char lineBuffer[maxLine]="";
|
char lineBuffer[maxLine]="";
|
||||||
string line, key, value;
|
string line, key, value;
|
||||||
size_t pos=0;
|
size_t pos=0;
|
||||||
this->path= path;
|
this->path= path;
|
||||||
|
|
||||||
|
//std::locale::global(std::locale(""));
|
||||||
|
bool is_utf8_language = valid_utf8_file(path.c_str());
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(__MINGW32__)
|
#if defined(WIN32) && !defined(__MINGW32__)
|
||||||
wstring wstr = utf8_decode(path);
|
wstring wstr = utf8_decode(path);
|
||||||
FILE *fp = _wfopen(wstr.c_str(), L"r");
|
FILE *fp = _wfopen(wstr.c_str(), L"r");
|
||||||
|
//wifstream fileStream(fp);
|
||||||
ifstream fileStream(fp);
|
ifstream fileStream(fp);
|
||||||
#else
|
#else
|
||||||
|
//wifstream fileStream;
|
||||||
ifstream fileStream;
|
ifstream fileStream;
|
||||||
fileStream.open(path.c_str(), ios_base::in);
|
fileStream.open(path.c_str(), ios_base::in);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(fileStream.is_open() == false){
|
if(fileStream.is_open() == false){
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path = [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str());
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path = [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str());
|
||||||
throw runtime_error("Can't open propertyMap file: " + path);
|
throw runtime_error("File NOT FOUND, can't open file: [" + path + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(clearCurrentProperties == true) {
|
if(clearCurrentProperties == true) {
|
||||||
propertyMap.clear();
|
propertyMap.clear();
|
||||||
}
|
}
|
||||||
while(!fileStream.eof()){
|
|
||||||
|
while(fileStream.eof() == false) {
|
||||||
|
lineBuffer[0]='\0';
|
||||||
fileStream.getline(lineBuffer, maxLine);
|
fileStream.getline(lineBuffer, maxLine);
|
||||||
lineBuffer[maxLine-1]='\0';
|
lineBuffer[maxLine-1]='\0';
|
||||||
//printf("\n[%s]\n",lineBuffer);
|
|
||||||
|
//printf("\n[%ls]\n",lineBuffer);
|
||||||
|
//printf("\n[%s]\n",&lineBuffer[0]);
|
||||||
|
|
||||||
|
// If the file is NOT in UTF-8 format convert each line
|
||||||
|
if(is_utf8_language == false && Font::forceLegacyFonts == false) {
|
||||||
|
char *utfStr = String::ConvertToUTF8(&lineBuffer[0]);
|
||||||
|
|
||||||
|
//printf("\nBefore [%s] After [%s]\n",&lineBuffer[0],utfStr);
|
||||||
|
|
||||||
|
memset(&lineBuffer[0],0,maxLine);
|
||||||
|
memcpy(&lineBuffer[0],&utfStr[0],strlen(utfStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(is_utf8_language == true && Font::forceLegacyFonts == true) {
|
||||||
|
//string line = lineBuffer;
|
||||||
|
//wstring wstr = fromUtf8(line.c_str(), line.size());
|
||||||
|
|
||||||
|
//vector <unsigned short> utf16result;
|
||||||
|
//utf8::utf8to16(line.begin(), line.end(), back_inserter(utf16result));
|
||||||
|
//vector <int> utf16result;
|
||||||
|
//utf8::utf8to32(line.begin(), line.end(), back_inserter(utf16result));
|
||||||
|
|
||||||
|
//printf("\nConverted UTF-8 from [%s] to [%s]\n",line.c_str(),utf16result[0]);
|
||||||
|
|
||||||
|
//char newBuf[4097]="";
|
||||||
|
//int newSize = ldap_x_utf8s_to_iso_8859_1s( &newBuf[0], line.c_str(), 4096 );
|
||||||
|
|
||||||
|
//std::wstring wstr = widen(newBuf);
|
||||||
|
//String st(wstr.c_str());
|
||||||
|
//String st(line.c_str());
|
||||||
|
|
||||||
|
//printf("\nConverted UTF-8 from [%s] to [%ls]\n",line.c_str(),wstr.c_str());
|
||||||
|
|
||||||
|
//const wchar_t *wBuf = &szPath[0];
|
||||||
|
//setlocale(LC_ALL, "en_CA.ISO-8559-15");
|
||||||
|
//std::locale::global(std::locale("en_CA.ISO-8559-15"));
|
||||||
|
//size_t size = 4096;
|
||||||
|
//char pMBBuffer[4096 + 1]="";
|
||||||
|
//wcstombs(&pMBBuffer[0], &lineBuffer[0], (size_t)size);// Convert to char* from TCHAR[]
|
||||||
|
//string newStr="";
|
||||||
|
//newStr.assign(&pMBBuffer[0]); // Now assign the char* to the string, and there you have it!!! :)
|
||||||
|
//printf("\nConverted UTF-8 from [%ls] to [%s]\n",&lineBuffer[0],newStr.c_str());
|
||||||
|
//std::locale::global(std::locale(""));
|
||||||
|
|
||||||
|
//char newBuf[4097]="";
|
||||||
|
//int newSize = ldap_x_utf8s_to_iso_8859_1s( &newBuf[0], &pMBBuffer[0], 4096 );
|
||||||
|
|
||||||
|
//String st(&lineBuffer[0]);
|
||||||
|
//printf("\nConverted UTF-8 from [%ls] to [%s]\n",&lineBuffer[0],&newBuf[0]);
|
||||||
|
|
||||||
|
//char newBuf[4097]="";
|
||||||
|
//int newSize = ldap_x_utf8s_to_iso_8859_1s( &newBuf[0], line.c_str(), 4096 );
|
||||||
|
|
||||||
|
//string newStr = conv_utf8_iso8859_7(line);
|
||||||
|
//printf("\nConverted UTF-8 from [%s] to [%s]\n",line.c_str(),newBuf);
|
||||||
|
// for(int i = 0; i < line.size(); ++i) {
|
||||||
|
// printf("to [%c][%d]\n",line[i],line[i]);
|
||||||
|
// }
|
||||||
|
//for(int i = 0; i < newStr.size(); ++i) {
|
||||||
|
// printf("to [%c][%d]\n",newStr[i],newStr[i]);
|
||||||
|
//}
|
||||||
|
|
||||||
|
// for(int i = 0; i < utf16result.size(); ++i) {
|
||||||
|
// printf("to [%c]\n",utf16result[i]);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//memset(&lineBuffer[0],0,maxLine);
|
||||||
|
//memcpy(&lineBuffer[0],&newBuf[0],newSize);
|
||||||
|
//}
|
||||||
|
//else {
|
||||||
|
//string line = lineBuffer;
|
||||||
|
//printf("\nNON UTF-8 from [%s]\n",line.c_str());
|
||||||
|
//for(int i = 0; i < line.size(); ++i) {
|
||||||
|
// printf("to [%c][%d]\n",line[i],line[i]);
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
//process line if it it not a comment
|
//process line if it it not a comment
|
||||||
if(lineBuffer[0] != ';') {
|
if(lineBuffer[0] != ';') {
|
||||||
|
//wstring wstr = lineBuffer;
|
||||||
|
//line.assign(wstr.begin(),wstr.end());
|
||||||
|
|
||||||
// gracefully handle win32 \r\n line endings
|
// gracefully handle win32 \r\n line endings
|
||||||
size_t len= strlen(lineBuffer);
|
size_t len= strlen(lineBuffer);
|
||||||
|
|
694
source/shared_lib/sources/util/string_utils.cpp
Normal file
694
source/shared_lib/sources/util/string_utils.cpp
Normal file
|
@ -0,0 +1,694 @@
|
||||||
|
/* TA3D, a remake of Total Annihilation
|
||||||
|
Copyright (C) 2005 Roland BROCHARD
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*/
|
||||||
|
|
||||||
|
//#include "../stdafx.h"
|
||||||
|
#include "string_utils.h"
|
||||||
|
|
||||||
|
#if TA3D_USE_BOOST == 1
|
||||||
|
# include <boost/algorithm/string.hpp>
|
||||||
|
# include <boost/algorithm/string/trim.hpp>
|
||||||
|
# include <boost/algorithm/string/split.hpp>
|
||||||
|
#else
|
||||||
|
# include <algorithm>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
//#include "../logs/logs.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Shared { namespace Util {
|
||||||
|
|
||||||
|
#if TA3D_USE_BOOST != 1
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
int stdLowerCase (int c)
|
||||||
|
{
|
||||||
|
return tolower(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stdUpperCase (int c)
|
||||||
|
{
|
||||||
|
return toupper(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String&
|
||||||
|
String::operator << (const wchar_t* v)
|
||||||
|
{
|
||||||
|
size_t l = wcslen(v);
|
||||||
|
char* b = new char[l + 1];
|
||||||
|
#ifndef WINDOWS
|
||||||
|
wcstombs(&b[0], v, l);
|
||||||
|
#else
|
||||||
|
size_t i;
|
||||||
|
wcstombs_s(&i, &b[0], l, v, l);
|
||||||
|
#endif
|
||||||
|
append(b);
|
||||||
|
delete b;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String&
|
||||||
|
String::toLower()
|
||||||
|
{
|
||||||
|
#if TA3D_USE_BOOST == 1
|
||||||
|
boost::to_lower(*this);
|
||||||
|
#else
|
||||||
|
std::transform (this->begin(), this->end(), this->begin(), stdLowerCase);
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String&
|
||||||
|
String::toUpper()
|
||||||
|
{
|
||||||
|
#if TA3D_USE_BOOST == 1
|
||||||
|
boost::to_upper(*this);
|
||||||
|
#else
|
||||||
|
std::transform (this->begin(), this->end(), this->begin(), stdUpperCase);
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool String::toBool() const
|
||||||
|
{
|
||||||
|
if (empty() || "0" == *this)
|
||||||
|
return false;
|
||||||
|
if ("1" == *this)
|
||||||
|
return true;
|
||||||
|
String s(*this);
|
||||||
|
s.toLower();
|
||||||
|
return ("true" == s || "on" == s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String&
|
||||||
|
String::trim(const String& trimChars)
|
||||||
|
{
|
||||||
|
// Find the first character position after excluding leading blank spaces
|
||||||
|
std::string::size_type startpos = this->find_first_not_of(trimChars);
|
||||||
|
// Find the first character position from reverse af
|
||||||
|
std::string::size_type endpos = this->find_last_not_of(trimChars);
|
||||||
|
|
||||||
|
// if all spaces or empty return an empty string
|
||||||
|
if ((std::string::npos == startpos) || (std::string::npos == endpos))
|
||||||
|
*this = "";
|
||||||
|
else
|
||||||
|
*this = this->substr(startpos, endpos - startpos + 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
String::split(String::Vector& out, const String& separators, const bool emptyBefore) const
|
||||||
|
{
|
||||||
|
// Empty the container
|
||||||
|
if (emptyBefore)
|
||||||
|
out.clear();
|
||||||
|
#if TA3D_USE_BOOST == 1
|
||||||
|
// TODO : Avoid string duplication
|
||||||
|
// Split
|
||||||
|
std::vector<std::string> v;
|
||||||
|
boost::algorithm::split(v, *this, boost::is_any_of(separators.c_str()));
|
||||||
|
// Copying
|
||||||
|
for(std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||||
|
out.push_back(*i);
|
||||||
|
#else
|
||||||
|
// TODO This method should be rewritten for better performance
|
||||||
|
String s(*this);
|
||||||
|
while (!s.empty())
|
||||||
|
{
|
||||||
|
String::size_type i = s.find_first_of(separators);
|
||||||
|
if (i == std::string::npos)
|
||||||
|
{
|
||||||
|
out.push_back(String::Trim(s));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.push_back(String::Trim(s.substr(0, i)));
|
||||||
|
s = s.substr(i + 1, s.size() - i - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
String::split(String::List& out, const String& separators, const bool emptyBefore) const
|
||||||
|
{
|
||||||
|
// Empty the container
|
||||||
|
if (emptyBefore)
|
||||||
|
out.clear();
|
||||||
|
#if TA3D_USE_BOOST == 1
|
||||||
|
// TODO : Avoid string duplication
|
||||||
|
// Split
|
||||||
|
std::vector<std::string> v;
|
||||||
|
boost::algorithm::split(v, *this, boost::is_any_of(separators.c_str()));
|
||||||
|
// Copying
|
||||||
|
for(std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||||
|
out.push_back(*i);
|
||||||
|
#else
|
||||||
|
// TODO This method should be rewritten for better performance
|
||||||
|
String s(*this);
|
||||||
|
while (!s.empty())
|
||||||
|
{
|
||||||
|
String::size_type i = s.find_first_of(separators);
|
||||||
|
if (i == std::string::npos)
|
||||||
|
{
|
||||||
|
out.push_back(String::Trim(s));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.push_back(String::Trim(s.substr(0, i)));
|
||||||
|
s = s.substr(i + 1, s.size() - i - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void String::ToKeyValue(const String& s, String& key, String& value, const enum String::CharCase chcase)
|
||||||
|
{
|
||||||
|
// The first usefull character
|
||||||
|
String::size_type pos = s.find_first_not_of(TA3D_WSTR_SEPARATORS);
|
||||||
|
if (pos == String::npos)
|
||||||
|
{
|
||||||
|
// The string is empty
|
||||||
|
key.clear();
|
||||||
|
value.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Begining of a section
|
||||||
|
if (s[pos] == '[')
|
||||||
|
{
|
||||||
|
key = "[";
|
||||||
|
pos = s.find_first_not_of(TA3D_WSTR_SEPARATORS, pos + 1);
|
||||||
|
String::size_type end = s.find_first_of(']', pos);
|
||||||
|
if (end != String::npos)
|
||||||
|
{
|
||||||
|
end = s.find_last_not_of(TA3D_WSTR_SEPARATORS, end - 1);
|
||||||
|
if (pos != String::npos && end != String::npos)
|
||||||
|
value = s.substr(pos, end - pos + 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The first `=` character
|
||||||
|
String::size_type equal = s.find_first_of('=', pos);
|
||||||
|
if (equal == String::npos)
|
||||||
|
{
|
||||||
|
// otherwise it is only a string
|
||||||
|
value.clear();
|
||||||
|
// But it may be a comment
|
||||||
|
String::size_type slashes = s.find("//", pos);
|
||||||
|
if (pos == slashes)
|
||||||
|
{
|
||||||
|
key.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String::size_type end = s.find_last_not_of(TA3D_WSTR_SEPARATORS, slashes - 1);
|
||||||
|
key = s.substr(pos, end - pos + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can extract our key
|
||||||
|
String::size_type end = s.find_last_not_of(TA3D_WSTR_SEPARATORS, equal - 1);
|
||||||
|
key = s.substr(pos, 1 + end - pos);
|
||||||
|
String::size_type slashes = key.rfind("//");
|
||||||
|
// Remove any comments
|
||||||
|
if (slashes != String::npos)
|
||||||
|
{
|
||||||
|
value.clear();
|
||||||
|
if (slashes == 0) // the key is a comment actually
|
||||||
|
key.clear();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get only the good part
|
||||||
|
slashes = key.find_last_not_of(TA3D_WSTR_SEPARATORS, slashes - 1);
|
||||||
|
key = key.substr(0, slashes + 1);
|
||||||
|
if (chcase == soIgnoreCase)
|
||||||
|
key.toLower();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (chcase == soIgnoreCase)
|
||||||
|
key.toLower();
|
||||||
|
|
||||||
|
// Left-Trim for the value
|
||||||
|
equal = s.find_first_not_of(TA3D_WSTR_SEPARATORS, equal + 1);
|
||||||
|
if (String::npos == equal)
|
||||||
|
{
|
||||||
|
value.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looking for the first semicolon
|
||||||
|
bool needReplaceSemicolons(false);
|
||||||
|
String::size_type semicolon = s.find_first_of(';', equal);
|
||||||
|
while (semicolon != String::npos && s[semicolon - 1] == '\\')
|
||||||
|
{
|
||||||
|
semicolon = s.find_first_of(';', semicolon + 1);
|
||||||
|
needReplaceSemicolons = true;
|
||||||
|
}
|
||||||
|
if (semicolon == String::npos)
|
||||||
|
{
|
||||||
|
// if none is present, looks for a comment to strip it
|
||||||
|
slashes = s.find("//", equal);
|
||||||
|
slashes = s.find_last_not_of(TA3D_WSTR_SEPARATORS, slashes - 1);
|
||||||
|
value = s.substr(equal, 1 + slashes - equal);
|
||||||
|
value.findAndReplace("\\r", "", soCaseSensitive);
|
||||||
|
value.findAndReplace("\\n", "\n", soCaseSensitive);
|
||||||
|
if (needReplaceSemicolons)
|
||||||
|
value.findAndReplace("\\;", ";", soCaseSensitive);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Remove spaces before the semicolon and after the `=`
|
||||||
|
semicolon = s.find_last_not_of(TA3D_WSTR_SEPARATORS, semicolon - 1);
|
||||||
|
|
||||||
|
// We can extract the value
|
||||||
|
if (semicolon >= equal)
|
||||||
|
{
|
||||||
|
value = s.substr(equal, 1 + semicolon - equal);
|
||||||
|
value.findAndReplace("\\r", "", soCaseSensitive);
|
||||||
|
value.findAndReplace("\\n", "\n", soCaseSensitive);
|
||||||
|
if (needReplaceSemicolons)
|
||||||
|
value.findAndReplace("\\;", ";", soCaseSensitive);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
value.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::convertAntiSlashesIntoSlashes()
|
||||||
|
{
|
||||||
|
for (String::iterator i = this->begin(); i != this->end(); ++i)
|
||||||
|
{
|
||||||
|
if (*i == '\\')
|
||||||
|
*i = '/';
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& String::convertSlashesIntoAntiSlashes()
|
||||||
|
{
|
||||||
|
for (String::iterator i = this->begin(); i != this->end(); ++i)
|
||||||
|
{
|
||||||
|
if (*i == '/')
|
||||||
|
*i = '\\';
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 String::hashValue() const
|
||||||
|
{
|
||||||
|
uint32 hash = 0;
|
||||||
|
for (String::const_iterator i = this->begin(); i != this->end(); ++i)
|
||||||
|
hash = (hash << 5) - hash + *i;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::FindInList(const String::Vector& l, const char* s)
|
||||||
|
{
|
||||||
|
int indx(0);
|
||||||
|
for (String::Vector::const_iterator i = l.begin(); i != l.end(); ++i, ++indx)
|
||||||
|
{
|
||||||
|
if(s == *i)
|
||||||
|
return indx;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int String::FindInList(const String::Vector& l, const String& s)
|
||||||
|
{
|
||||||
|
int indx(0);
|
||||||
|
for (String::Vector::const_iterator i = l.begin(); i != l.end(); ++i, ++indx)
|
||||||
|
{
|
||||||
|
if(s == *i)
|
||||||
|
return indx;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* String::ConvertToUTF8(const char* s)
|
||||||
|
{
|
||||||
|
if (NULL != s && *s != '\0')
|
||||||
|
return ConvertToUTF8(s, strlen(s));
|
||||||
|
char* ret = new char[1];
|
||||||
|
//LOG_ASSERT(NULL != ret);
|
||||||
|
assert(NULL != ret);
|
||||||
|
*ret = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* String::ConvertToUTF8(const char* s, const uint32 len)
|
||||||
|
{
|
||||||
|
uint32 nws;
|
||||||
|
return ConvertToUTF8(s, len, nws);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::ASCIItoUTF8(const byte c, byte *out) {
|
||||||
|
if (c < 0x80)
|
||||||
|
{
|
||||||
|
*out = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if(c < 0xC0)
|
||||||
|
{
|
||||||
|
out[0] = 0xC2;
|
||||||
|
out[1] = c;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
out[0] = 0xC3;
|
||||||
|
out[1] = c - 0x40;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* String::ConvertToUTF8(const char* s, uint32 len, uint32& newSize)
|
||||||
|
{
|
||||||
|
if (NULL == s || '\0' == *s)
|
||||||
|
{
|
||||||
|
char* ret = new char[1];
|
||||||
|
//LOG_ASSERT(NULL != ret);
|
||||||
|
assert(NULL != ret);
|
||||||
|
*ret = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
byte tmp[4];
|
||||||
|
newSize = 1;
|
||||||
|
for(byte *p = (byte*)s ; *p ; p++)
|
||||||
|
newSize += ASCIItoUTF8(*p, tmp);
|
||||||
|
|
||||||
|
char* ret = new char[newSize];
|
||||||
|
//LOG_ASSERT(NULL != ret);
|
||||||
|
assert(NULL != ret);
|
||||||
|
|
||||||
|
byte *q = (byte*)ret;
|
||||||
|
for(byte *p = (byte*)s ; *p ; p++)
|
||||||
|
q += ASCIItoUTF8(*p, q);
|
||||||
|
*q = '\0'; // A bit paranoid
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String String::ConvertToUTF8(const String& s)
|
||||||
|
{
|
||||||
|
if (s.empty())
|
||||||
|
return String();
|
||||||
|
char* ret = ConvertToUTF8(s.c_str(), s.size());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
String s(ret); // TODO Find a way to not use a temporary string
|
||||||
|
delete[] ret;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::findAndReplace(char toSearch, const char replaceWith, const enum String::CharCase option)
|
||||||
|
{
|
||||||
|
if (option == soIgnoreCase)
|
||||||
|
{
|
||||||
|
toSearch = tolower(toSearch);
|
||||||
|
for (String::iterator i = this->begin(); i != this->end(); ++i)
|
||||||
|
{
|
||||||
|
if (tolower(*i) == toSearch)
|
||||||
|
*i = replaceWith;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (String::iterator i = this->begin(); i != this->end(); ++i)
|
||||||
|
{
|
||||||
|
if (*i == toSearch)
|
||||||
|
*i = replaceWith;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::findAndReplace(const String& toSearch, const String& replaceWith, const enum String::CharCase option)
|
||||||
|
{
|
||||||
|
if (soCaseSensitive == option)
|
||||||
|
{
|
||||||
|
String::size_type p = 0;
|
||||||
|
String::size_type siz = toSearch.size();
|
||||||
|
while ((p = this->find(toSearch, p)) != String::npos)
|
||||||
|
this->replace(p, siz, replaceWith);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*this = String::ToLower(*this).findAndReplace(String::ToLower(toSearch), replaceWith, soCaseSensitive);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::format(const String& f, ...)
|
||||||
|
{
|
||||||
|
va_list parg;
|
||||||
|
va_start(parg, f);
|
||||||
|
|
||||||
|
this->clear();
|
||||||
|
vappendFormat(f.c_str(), parg);
|
||||||
|
|
||||||
|
va_end(parg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::format(const char* f, ...)
|
||||||
|
{
|
||||||
|
va_list parg;
|
||||||
|
va_start(parg, f);
|
||||||
|
|
||||||
|
this->clear();
|
||||||
|
vappendFormat(f, parg);
|
||||||
|
|
||||||
|
va_end(parg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::appendFormat(const String& f, ...)
|
||||||
|
{
|
||||||
|
va_list parg;
|
||||||
|
va_start(parg, f);
|
||||||
|
|
||||||
|
vappendFormat(f.c_str(), parg);
|
||||||
|
|
||||||
|
va_end(parg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::appendFormat(const char* f, ...)
|
||||||
|
{
|
||||||
|
va_list parg;
|
||||||
|
va_start(parg, f);
|
||||||
|
|
||||||
|
vappendFormat(f, parg);
|
||||||
|
|
||||||
|
va_end(parg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::vappendFormat(const char* f, va_list parg)
|
||||||
|
{
|
||||||
|
char* b;
|
||||||
|
#if defined TA3D_PLATFORM_WINDOWS
|
||||||
|
// Implement vasprintf() by hand with two calls to vsnprintf()
|
||||||
|
// Remove this when Microsoft adds support for vasprintf()
|
||||||
|
#if defined TA3D_PLATFORM_MSVC
|
||||||
|
int sizeneeded = _vsnprintf(NULL, 0, f, parg) + 1;
|
||||||
|
#else
|
||||||
|
int sizeneeded = vsnprintf(NULL, 0, f, parg) + 1;
|
||||||
|
#endif
|
||||||
|
if (sizeneeded < 0)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
b = new char[sizeneeded];
|
||||||
|
if (b == NULL)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#if defined TA3D_PLATFORM_MSVC
|
||||||
|
if (_vsnprintf(b, sizeneeded, f, parg) < 0)
|
||||||
|
#else
|
||||||
|
if (vsnprintf(b, sizeneeded, f, parg) < 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
delete[] b;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (vasprintf(&b, f, parg) < 0)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
this->append(b);
|
||||||
|
delete[] b;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String String::Format(const String& f, ...)
|
||||||
|
{
|
||||||
|
va_list parg;
|
||||||
|
va_start(parg, f);
|
||||||
|
|
||||||
|
String s;
|
||||||
|
s.vappendFormat(f.c_str(), parg);
|
||||||
|
|
||||||
|
va_end(parg);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::Format(const char* f, ...)
|
||||||
|
{
|
||||||
|
va_list parg;
|
||||||
|
va_start(parg, f);
|
||||||
|
|
||||||
|
String s;
|
||||||
|
s.vappendFormat(f, parg);
|
||||||
|
|
||||||
|
va_end(parg);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::match(const String &pattern)
|
||||||
|
{
|
||||||
|
if (pattern.empty())
|
||||||
|
return empty();
|
||||||
|
|
||||||
|
int e = 0;
|
||||||
|
int prev = -1;
|
||||||
|
for(int i = 0 ; i < size() ; i++)
|
||||||
|
if (pattern[e] == '*')
|
||||||
|
{
|
||||||
|
if (e + 1 == pattern.size())
|
||||||
|
return true;
|
||||||
|
while(pattern[e+1] == '*') e++;
|
||||||
|
if (e + 1 == pattern.size())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
prev = e;
|
||||||
|
if (pattern[e+1] == (*this)[i])
|
||||||
|
e+=2;
|
||||||
|
}
|
||||||
|
else if(pattern[e] == (*this)[i])
|
||||||
|
e++;
|
||||||
|
else if(prev >= 0)
|
||||||
|
e = prev;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return e == pattern.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::substrUTF8(int pos, int len) const
|
||||||
|
{
|
||||||
|
if (len < 0)
|
||||||
|
len = sizeUTF8() - len + 1 - pos;
|
||||||
|
String res;
|
||||||
|
int utf8_pos = 0;
|
||||||
|
for(; pos > 0 ; pos--)
|
||||||
|
if (((byte)(*this)[utf8_pos]) >= 0xC0)
|
||||||
|
{
|
||||||
|
utf8_pos++;
|
||||||
|
while (((byte)(*this)[utf8_pos]) >= 0x80 && ((byte)(*this)[utf8_pos]) < 0xC0)
|
||||||
|
utf8_pos++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
utf8_pos++;
|
||||||
|
|
||||||
|
for(; len > 0 ; len--)
|
||||||
|
{
|
||||||
|
if (((byte)(*this)[utf8_pos]) >= 0x80)
|
||||||
|
{
|
||||||
|
res << (char)(*this)[utf8_pos];
|
||||||
|
utf8_pos++;
|
||||||
|
while (((byte)(*this)[utf8_pos]) >= 0x80 && ((byte)(*this)[utf8_pos]) < 0xC0)
|
||||||
|
{
|
||||||
|
res << (char)(*this)[utf8_pos];
|
||||||
|
utf8_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res << ((char)(*this)[utf8_pos]);
|
||||||
|
utf8_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::sizeUTF8() const
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
for(int i = 0 ; i < this->size() ; i++)
|
||||||
|
if (((byte)(*this)[i]) >= 0xC0 || ((byte)(*this)[i]) < 0x80)
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
WString::WString(const char* s)
|
||||||
|
{
|
||||||
|
if (s)
|
||||||
|
fromUtf8(s, strlen(s));
|
||||||
|
else
|
||||||
|
pBuffer[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WString::WString(const String& s)
|
||||||
|
{
|
||||||
|
fromUtf8(s.c_str(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WString::fromUtf8(const char* str, size_t length)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
for(int i = 0 ; i < length; i++)
|
||||||
|
{
|
||||||
|
if (((byte)str[i]) < 0x80)
|
||||||
|
{
|
||||||
|
pBuffer[len++] = ((byte)str[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (((byte)str[i]) >= 0xC0)
|
||||||
|
{
|
||||||
|
wchar_t c = ((byte)str[i++]) - 0xC0;
|
||||||
|
while(((byte)str[i]) >= 0x80)
|
||||||
|
c = (c << 6) | (((byte)str[i++]) - 0x80);
|
||||||
|
--i;
|
||||||
|
pBuffer[len++] = c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pBuffer[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
Loading…
Reference in New Issue
Block a user