- 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");
|
||||
int displayFontSize = computeFontSize(config.getInt("FontDisplayBaseSize"));
|
||||
|
||||
//printf("Checking if langfile has custom FontDisplayPostfix\n");
|
||||
|
||||
if(lang.hasString("FontDisplayPrefix") == true) {
|
||||
displayFontNamePrefix = lang.get("FontDisplayPrefix");
|
||||
}
|
||||
|
@ -143,11 +145,19 @@ void CoreData::load() {
|
|||
displayFontSize = strToInt(lang.get("FontDisplayBaseSize"));
|
||||
}
|
||||
|
||||
string displayFontName=displayFontNamePrefix+intToStr(displayFontSize)+displayFontNamePostfix;
|
||||
//printf("displayFontNamePostfix [%s]\n",displayFontNamePostfix.c_str());
|
||||
|
||||
string displayFontName = displayFontNamePrefix + intToStr(displayFontSize) + displayFontNamePostfix;
|
||||
|
||||
displayFont= renderer.newFont(rsGlobal);
|
||||
displayFont->setType(displayFontName,config.getString("FontDisplay",""));
|
||||
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);
|
||||
|
||||
|
@ -166,10 +176,17 @@ void CoreData::load() {
|
|||
displayFontNameSmallSize = strToInt(lang.get("FontDisplaySmallBaseSize"));
|
||||
}
|
||||
|
||||
string displayFontNameSmall=displayFontNameSmallPrefix+intToStr(displayFontNameSmallSize)+displayFontNameSmallPostfix;
|
||||
string displayFontNameSmall = displayFontNameSmallPrefix + intToStr(displayFontNameSmallSize) + displayFontNameSmallPostfix;
|
||||
|
||||
displayFontSmall= renderer.newFont(rsGlobal);
|
||||
displayFontSmall->setType(displayFontNameSmall,config.getString("FontDisplay",""));
|
||||
displayFontSmall->setType(displayFontNameSmall,config.getString("FontSmallDisplay",""));
|
||||
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);
|
||||
|
||||
|
@ -187,11 +204,19 @@ void CoreData::load() {
|
|||
menuFontNameNormalSize = strToInt(lang.get("FontMenuNormalBaseSize"));
|
||||
}
|
||||
|
||||
string menuFontNameNormal= menuFontNameNormalPrefix+intToStr(menuFontNameNormalSize)+menuFontNameNormalPostfix;
|
||||
string menuFontNameNormal= menuFontNameNormalPrefix + intToStr(menuFontNameNormalSize) + menuFontNameNormalPostfix;
|
||||
|
||||
menuFontNormal= renderer.newFont(rsGlobal);
|
||||
menuFontNormal->setType(menuFontNameNormal,config.getString("FontMenuNormal",""));
|
||||
menuFontNormal->setSize(menuFontNameNormalSize);
|
||||
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);
|
||||
|
||||
|
@ -214,6 +239,12 @@ void CoreData::load() {
|
|||
menuFontBig= renderer.newFont(rsGlobal);
|
||||
menuFontBig->setType(menuFontNameBig,config.getString("FontMenuBig",""));
|
||||
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);
|
||||
|
||||
|
@ -231,11 +262,17 @@ void CoreData::load() {
|
|||
menuFontNameVeryBigSize = strToInt(lang.get("FontMenuVeryBigBaseSize"));
|
||||
}
|
||||
|
||||
string menuFontNameVeryBig= menuFontNameVeryBigPrefix+intToStr(menuFontNameVeryBigSize)+menuFontNameVeryBigPostfix;
|
||||
string menuFontNameVeryBig= menuFontNameVeryBigPrefix + intToStr(menuFontNameVeryBigSize) + menuFontNameVeryBigPostfix;
|
||||
|
||||
menuFontVeryBig= renderer.newFont(rsGlobal);
|
||||
menuFontVeryBig->setType(menuFontNameVeryBig,config.getString("FontMenuBig",""));
|
||||
menuFontVeryBig->setType(menuFontNameVeryBig,config.getString("FontMenuVeryBig",""));
|
||||
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);
|
||||
|
||||
|
@ -254,11 +291,17 @@ void CoreData::load() {
|
|||
consoleFontNameSize = strToInt(lang.get("FontConsoleBaseSize"));
|
||||
}
|
||||
|
||||
string consoleFontName= consoleFontNamePrefix+intToStr(consoleFontNameSize)+consoleFontNamePostfix;
|
||||
string consoleFontName= consoleFontNamePrefix + intToStr(consoleFontNameSize) + consoleFontNamePostfix;
|
||||
|
||||
consoleFont= renderer.newFont(rsGlobal);
|
||||
consoleFont->setType(consoleFontName,config.getString("FontConsole",""));
|
||||
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);
|
||||
|
||||
|
@ -273,6 +316,7 @@ void CoreData::load() {
|
|||
menuMusic.open(dir+"/menu/music/menu_music.ogg");
|
||||
menuMusic.setNext(&menuMusic);
|
||||
waterSounds.resize(6);
|
||||
|
||||
for(int i=0; i<6; ++i){
|
||||
waterSounds[i]= new StaticSound();
|
||||
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::Texture3D;
|
||||
using Shared::Graphics::Font2D;
|
||||
using Shared::Graphics::Font3D;
|
||||
using Shared::Sound::StrSound;
|
||||
using Shared::Sound::StaticSound;
|
||||
|
||||
|
@ -67,6 +68,13 @@ private:
|
|||
Font2D *menuFontVeryBig;
|
||||
Font2D *consoleFont;
|
||||
|
||||
Font3D *displayFont3D;
|
||||
Font3D *menuFontNormal3D;
|
||||
Font3D *displayFontSmall3D;
|
||||
Font3D *menuFontBig3D;
|
||||
Font3D *menuFontVeryBig3D;
|
||||
Font3D *consoleFont3D;
|
||||
|
||||
public:
|
||||
static CoreData &getInstance();
|
||||
~CoreData();
|
||||
|
@ -107,6 +115,13 @@ public:
|
|||
Font2D *getMenuFontVeryBig() const {return menuFontVeryBig;}
|
||||
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:
|
||||
CoreData(){};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "platform_util.h"
|
||||
#include "game_constants.h"
|
||||
#include "game_util.h"
|
||||
#include "platform_common.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -30,7 +31,12 @@ namespace Glest{ namespace Game{
|
|||
// class Lang
|
||||
// =====================================================
|
||||
|
||||
Lang &Lang::getInstance(){
|
||||
Lang::Lang() {
|
||||
language = "";
|
||||
is_utf8_language = false;
|
||||
}
|
||||
|
||||
Lang &Lang::getInstance() {
|
||||
static Lang lang;
|
||||
return lang;
|
||||
}
|
||||
|
@ -47,9 +53,14 @@ void Lang::loadStrings(const string &language, Properties &properties, bool file
|
|||
if(fileMustExist == false && fileExists(languageFile) == false) {
|
||||
return;
|
||||
}
|
||||
is_utf8_language = valid_utf8_file(languageFile.c_str());
|
||||
properties.load(languageFile);
|
||||
}
|
||||
|
||||
bool Lang::isUTF8Language() const {
|
||||
return is_utf8_language;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
|
|
|
@ -28,24 +28,30 @@ using Shared::Util::Properties;
|
|||
class Lang {
|
||||
private:
|
||||
string language;
|
||||
bool is_utf8_language;
|
||||
|
||||
Properties strings;
|
||||
Properties scenarioStrings;
|
||||
|
||||
std::map<string,Properties> otherLanguageStrings;
|
||||
|
||||
private:
|
||||
Lang(){};
|
||||
Lang();
|
||||
void loadStrings(const string &language, Properties &properties, bool fileMustExist);
|
||||
|
||||
public:
|
||||
static Lang &getInstance();
|
||||
|
||||
void loadStrings(const string &language);
|
||||
void loadScenarioStrings(const string &scenarioDir, const string &scenarioName);
|
||||
|
||||
string get(const string &s,string language="");
|
||||
bool hasString(const string &s, string language="");
|
||||
string getScenarioString(const string &s);
|
||||
|
||||
string getLanguage() const { return language; }
|
||||
bool isLanguageLocal(string compareLanguage) const;
|
||||
bool isUTF8Language() const;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -159,6 +159,7 @@ Renderer::Renderer() {
|
|||
showDebugUILevel = debugui_fps;
|
||||
modelRenderer = NULL;
|
||||
textRenderer = NULL;
|
||||
textRenderer3D = NULL;
|
||||
particleRenderer = NULL;
|
||||
saveScreenShotThread = NULL;
|
||||
mapSurfaceData.clear();
|
||||
|
@ -191,6 +192,7 @@ Renderer::Renderer() {
|
|||
|
||||
modelRenderer= graphicsFactory->newModelRenderer();
|
||||
textRenderer= graphicsFactory->newTextRenderer2D();
|
||||
textRenderer3D = graphicsFactory->newTextRenderer3D();
|
||||
particleRenderer= graphicsFactory->newParticleRenderer();
|
||||
|
||||
//resources
|
||||
|
@ -238,6 +240,8 @@ Renderer::~Renderer() {
|
|||
modelRenderer = NULL;
|
||||
delete textRenderer;
|
||||
textRenderer = NULL;
|
||||
delete textRenderer3D;
|
||||
textRenderer3D = NULL;
|
||||
delete particleRenderer;
|
||||
particleRenderer = NULL;
|
||||
|
||||
|
@ -579,6 +583,10 @@ Font2D *Renderer::newFont(ResourceScope rs){
|
|||
return fontManager[rs]->newFont2D();
|
||||
}
|
||||
|
||||
Font3D *Renderer::newFont3D(ResourceScope rs){
|
||||
return fontManager[rs]->newFont3D();
|
||||
}
|
||||
|
||||
void Renderer::manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs){
|
||||
particleManager[rs]->manage(particleSystem);
|
||||
}
|
||||
|
@ -687,9 +695,11 @@ void Renderer::loadGameCameraMatrix() {
|
|||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glRotatef(gameCamera->getVAng(), -1, 0, 0);
|
||||
glRotatef(gameCamera->getHAng(), 0, 1, 0);
|
||||
glTranslatef(-gameCamera->getPos().x, -gameCamera->getPos().y, -gameCamera->getPos().z);
|
||||
if(gameCamera != NULL) {
|
||||
glRotatef(gameCamera->getVAng(), -1, 0, 0);
|
||||
glRotatef(gameCamera->getHAng(), 0, 1, 0);
|
||||
glTranslatef(-gameCamera->getPos().x, -gameCamera->getPos().y, -gameCamera->getPos().z);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::loadCameraMatrix(const Camera *camera) {
|
||||
|
@ -1229,7 +1239,43 @@ Vec2i computeCenteredPos(const string &text, Font2D *font, int x, int y) {
|
|||
return textPos;
|
||||
}
|
||||
|
||||
void Renderer::renderText(const string &text, Font2D *font, float alpha, int x, int y, bool centered){
|
||||
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) {
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
glColor4fv(Vec4f(1.f, 1.f, 1.f, alpha).ptr());
|
||||
|
@ -1243,6 +1289,19 @@ void Renderer::renderText(const string &text, Font2D *font, float alpha, int x,
|
|||
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){
|
||||
glPushAttrib(GL_CURRENT_BIT);
|
||||
glColor3fv(color.ptr());
|
||||
|
@ -1256,6 +1315,20 @@ void Renderer::renderText(const string &text, Font2D *font, const Vec3f &color,
|
|||
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){
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
|
@ -1270,6 +1343,29 @@ void Renderer::renderText(const string &text, Font2D *font, const Vec4f &color,
|
|||
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){
|
||||
if(font == NULL) {
|
||||
throw runtime_error("font == NULL");
|
||||
|
@ -1280,11 +1376,13 @@ void Renderer::renderTextShadow(const string &text, Font2D *font,const Vec4f &co
|
|||
Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
|
||||
|
||||
textRenderer->begin(font);
|
||||
if(color.w<0.5) {
|
||||
if(color.w < 0.5) {
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
|
||||
textRenderer->render(text, pos.x-1.0f, pos.y-1.0f);
|
||||
}
|
||||
glColor3f(color.x,color.y,color.z);
|
||||
|
||||
textRenderer->render(text, pos.x, pos.y);
|
||||
textRenderer->end();
|
||||
|
||||
|
@ -1460,9 +1558,16 @@ void Renderer::renderButton(GraphicButton *button, const Vec4f *fontColorOverrid
|
|||
Vec2i textPos= Vec2i(x+w/2, y+h/2);
|
||||
|
||||
if(button->getEditable()) {
|
||||
Font2D *font = button->getFont();
|
||||
//Font3D *font3d = ConvertFont2DTo3D(button->getFont());
|
||||
renderText(
|
||||
button->getText(), button->getFont(), color,
|
||||
button->getText(), font, color,
|
||||
x+w/2, y+h/2, true);
|
||||
//delete font3d;
|
||||
|
||||
// renderText(
|
||||
// button->getText(), button->getFont(), color,
|
||||
// x+w/2, y+h/2, true);
|
||||
}
|
||||
else {
|
||||
renderText(
|
||||
|
@ -4676,6 +4781,60 @@ void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2,
|
|||
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,
|
||||
string prefixLabel,bool centeredText) {
|
||||
|
||||
|
@ -4719,6 +4878,7 @@ void Renderer::renderProgressBar(int size, int x, int y, Font2D *font, int custo
|
|||
|
||||
//text
|
||||
glColor3fv(defColor.ptr());
|
||||
|
||||
textRenderer->begin(font);
|
||||
if(centeredText == true) {
|
||||
textRenderer->render(renderText.c_str(), x + maxSize / 2, y, centeredText);
|
||||
|
|
|
@ -221,6 +221,7 @@ private:
|
|||
//renderers
|
||||
ModelRenderer *modelRenderer;
|
||||
TextRenderer2D *textRenderer;
|
||||
TextRenderer3D *textRenderer3D;
|
||||
ParticleRenderer *particleRenderer;
|
||||
|
||||
//texture managers
|
||||
|
@ -322,6 +323,8 @@ public:
|
|||
Texture2D *newTexture2D(ResourceScope rs);
|
||||
Texture3D *newTexture3D(ResourceScope rs);
|
||||
Font2D *newFont(ResourceScope rs);
|
||||
Font3D *newFont3D(ResourceScope rs);
|
||||
|
||||
TextRenderer2D *getTextRenderer() const {return textRenderer;}
|
||||
void manageParticleSystem(ParticleSystem *particleSystem, 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 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
|
||||
void renderLabel(GraphicLabel *label);
|
||||
void renderLabel(GraphicLabel *label,const Vec3f *color);
|
||||
|
|
|
@ -125,6 +125,7 @@ const char *GAME_ARGS[] = {
|
|||
"--disable-backtrace",
|
||||
"--disable-vbo",
|
||||
"--disable-sound",
|
||||
"--enable-legacyfonts",
|
||||
"--verbose"
|
||||
|
||||
};
|
||||
|
@ -159,6 +160,7 @@ enum GAME_ARG_TYPE {
|
|||
GAME_ARG_DISABLE_BACKTRACE,
|
||||
GAME_ARG_DISABLE_VBO,
|
||||
GAME_ARG_DISABLE_SOUND,
|
||||
GAME_ARG_ENABLE_LEGACYFONTS,
|
||||
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 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\n");
|
||||
|
@ -2445,6 +2449,11 @@ int glestMain(int argc, char** argv) {
|
|||
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
|
||||
SystemFlags::ENABLE_THREADED_LOGGING = config.getBool("ThreadedLogging","true");
|
||||
FontGl::setDefault_fontType(config.getString("DefaultFont",FontGl::getDefault_fontType().c_str()));
|
||||
|
@ -2573,6 +2582,10 @@ int glestMain(int argc, char** argv) {
|
|||
#endif
|
||||
}
|
||||
|
||||
if( lang.hasString("FONT_YOFFSET_FACTOR")) {
|
||||
FontMetrics::DEFAULT_Y_OFFSET_FACTOR = strToFloat(lang.get("FONT_YOFFSET_FACTOR"));
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
// Win32 overrides for fonts (just in case they must be different)
|
||||
if( lang.hasString("FONT_CHARCOUNT_WINDOWS")) {
|
||||
|
@ -2598,6 +2611,10 @@ int glestMain(int argc, char** argv) {
|
|||
_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
|
||||
#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);
|
||||
|
|
|
@ -82,12 +82,12 @@ MainMenu::~MainMenu() {
|
|||
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
}
|
||||
|
||||
void MainMenu::init(){
|
||||
void MainMenu::init() {
|
||||
Renderer::getInstance().initMenu(this);
|
||||
}
|
||||
|
||||
//asynchronus render update
|
||||
void MainMenu::render(){
|
||||
void MainMenu::render() {
|
||||
|
||||
Config &config= Config::getInstance();
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
@ -110,7 +110,6 @@ void MainMenu::render(){
|
|||
state->render();
|
||||
renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim);
|
||||
|
||||
//if(config.getBool("DebugMode")){
|
||||
if(renderer.getShowDebugUI() == true) {
|
||||
renderer.renderText(
|
||||
"FPS: " + intToStr(lastFps),
|
||||
|
|
|
@ -13,11 +13,12 @@
|
|||
#define _SHARED_GRAPHICS_FONT_H_
|
||||
|
||||
#include <string>
|
||||
#include "font_text.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
class Text;
|
||||
//class Text;
|
||||
|
||||
namespace Shared { namespace Graphics {
|
||||
|
||||
|
@ -26,15 +27,23 @@ namespace Shared { namespace Graphics {
|
|||
// =====================================================
|
||||
|
||||
class FontMetrics {
|
||||
|
||||
private:
|
||||
float *widths;
|
||||
float height;
|
||||
|
||||
float yOffsetFactor;
|
||||
Text *textHandler;
|
||||
|
||||
public:
|
||||
static float DEFAULT_Y_OFFSET_FACTOR;
|
||||
|
||||
FontMetrics(Text *textHandler=NULL);
|
||||
~FontMetrics();
|
||||
|
||||
void setYOffsetFactor(float yOffsetFactor);
|
||||
float getYOffsetFactor() const;
|
||||
|
||||
void setTextHandler(Text *textHandler);
|
||||
Text * getTextHandler();
|
||||
|
||||
|
@ -54,6 +63,7 @@ public:
|
|||
static int charCount;
|
||||
static std::string fontTypeName;
|
||||
static bool fontIsMultibyte;
|
||||
static bool forceLegacyFonts;
|
||||
|
||||
public:
|
||||
enum Width {
|
||||
|
@ -65,13 +75,14 @@ protected:
|
|||
string type;
|
||||
int width;
|
||||
bool inited;
|
||||
int size;
|
||||
FontMetrics metrics;
|
||||
|
||||
Text *textHandler;
|
||||
|
||||
public:
|
||||
//constructor & destructor
|
||||
Font();
|
||||
Font(FontTextHandlerType type);
|
||||
virtual ~Font();
|
||||
virtual void init()=0;
|
||||
virtual void end()=0;
|
||||
|
@ -81,10 +92,16 @@ public:
|
|||
int getWidth() const;
|
||||
FontMetrics *getMetrics() {return &metrics;}
|
||||
Text * getTextHandler() {return textHandler;}
|
||||
float getYOffsetFactor() const;
|
||||
string getType() const;
|
||||
|
||||
//set
|
||||
void setYOffsetFactor(float yOffsetFactor);
|
||||
void setType(string typeX11, string typeGeneric);
|
||||
void setWidth(int width);
|
||||
|
||||
int getSize() const;
|
||||
void setSize(int size);
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
|
@ -93,14 +110,11 @@ public:
|
|||
|
||||
class Font2D: public Font {
|
||||
protected:
|
||||
int size;
|
||||
//int size;
|
||||
|
||||
public:
|
||||
Font2D();
|
||||
Font2D(FontTextHandlerType type=ftht_2D);
|
||||
virtual ~Font2D() {};
|
||||
|
||||
int getSize() const;
|
||||
void setSize(int size);
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
|
@ -112,13 +126,15 @@ protected:
|
|||
float depth;
|
||||
|
||||
public:
|
||||
Font3D();
|
||||
Font3D(FontTextHandlerType type=ftht_3D);
|
||||
virtual ~Font3D() {};
|
||||
|
||||
float getDepth() const {return depth;}
|
||||
void setDepth(float depth) {this->depth= depth;}
|
||||
};
|
||||
|
||||
Font3D *ConvertFont2DTo3D(Font2D *font);
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,17 +15,25 @@
|
|||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
enum FontTextHandlerType {
|
||||
ftht_2D,
|
||||
ftht_3D
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class upon which all text rendering calls are made.
|
||||
*/
|
||||
//====================================================================
|
||||
class Text
|
||||
{
|
||||
protected:
|
||||
FontTextHandlerType type;
|
||||
public:
|
||||
|
||||
static std::string DEFAULT_FONT_PATH;
|
||||
|
||||
Text();
|
||||
Text(FontTextHandlerType type);
|
||||
virtual ~Text();
|
||||
|
||||
virtual void init(string fontName, int fontSize);
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
#include "font_text.h"
|
||||
|
||||
namespace Shared{ namespace Graphics{ namespace Gl{
|
||||
namespace Shared { namespace Graphics { namespace Gl {
|
||||
|
||||
/**
|
||||
* Use FTGL for rendering text in OpenGL
|
||||
*/
|
||||
|
@ -27,7 +28,7 @@ class TextFTGL : public Text
|
|||
{
|
||||
public:
|
||||
|
||||
TextFTGL();
|
||||
TextFTGL(FontTextHandlerType type);
|
||||
virtual ~TextFTGL();
|
||||
virtual void init(string fontName, int fontSize);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace Shared { namespace Graphics { namespace Gl {
|
|||
|
||||
class Font2DGl;
|
||||
class Font3DGl;
|
||||
class TextRenderer3DGl;
|
||||
|
||||
// =====================================================
|
||||
// class TextRenderer2DGl
|
||||
|
@ -29,6 +30,9 @@ private:
|
|||
Font2DGl *font;
|
||||
bool rendering;
|
||||
|
||||
//Font3DGl *font3D;
|
||||
//TextRenderer3DGl *tester;
|
||||
|
||||
public:
|
||||
TextRenderer2DGl();
|
||||
virtual ~TextRenderer2DGl();
|
||||
|
@ -42,7 +46,7 @@ public:
|
|||
// class TextRenderer3DGl
|
||||
// =====================================================
|
||||
|
||||
class TextRenderer3DGl: public TextRenderer3D{
|
||||
class TextRenderer3DGl: public TextRenderer3D {
|
||||
private:
|
||||
Font3DGl *font;
|
||||
bool rendering;
|
||||
|
@ -52,7 +56,7 @@ public:
|
|||
virtual ~TextRenderer3DGl();
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
virtual ~TextRenderer3D(){};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -213,6 +213,8 @@ string getFullFileArchiveExtractCommand(string fileArchiveExtractCommand,
|
|||
bool executeShellCommand(string cmd,int expectedResult=IGNORE_CMD_RESULT_VALUE);
|
||||
string executable_path(string exeName,bool includeExeNameInPath=false);
|
||||
|
||||
bool valid_utf8_file(const char* file_name);
|
||||
|
||||
class ValueCheckerVault {
|
||||
|
||||
protected:
|
||||
|
|
|
@ -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__
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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 "conversion.h"
|
||||
|
||||
#include "font_text.h"
|
||||
#ifdef USE_FTGL
|
||||
|
||||
#include "font_textFTGL.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
//#include "string_utils.h"
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Graphics::Gl;
|
||||
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -31,9 +32,11 @@ using namespace Shared::Util;
|
|||
namespace Shared { namespace Graphics {
|
||||
|
||||
// Init statics
|
||||
int Font::charCount = 256;
|
||||
std::string Font::fontTypeName = "Times New Roman";
|
||||
bool Font::fontIsMultibyte = false;
|
||||
int Font::charCount = 256;
|
||||
std::string Font::fontTypeName = "Times New Roman";
|
||||
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->widths = new float[Font::charCount];
|
||||
this->height = 0;
|
||||
this->yOffsetFactor = FontMetrics::DEFAULT_Y_OFFSET_FACTOR;
|
||||
|
||||
for(int i=0; i < Font::charCount; ++i) {
|
||||
widths[i]= 0;
|
||||
|
@ -55,6 +59,14 @@ FontMetrics::~FontMetrics() {
|
|||
widths = NULL;
|
||||
}
|
||||
|
||||
void FontMetrics::setYOffsetFactor(float yOffsetFactor) {
|
||||
this->yOffsetFactor = yOffsetFactor;
|
||||
}
|
||||
|
||||
float FontMetrics::getYOffsetFactor() const {
|
||||
return this->yOffsetFactor;
|
||||
}
|
||||
|
||||
void FontMetrics::setTextHandler(Text *textHandler) {
|
||||
this->textHandler = textHandler;
|
||||
}
|
||||
|
@ -100,15 +112,27 @@ float FontMetrics::getHeight() const {
|
|||
// class Font
|
||||
// ===============================================
|
||||
|
||||
Font::Font() {
|
||||
Font::Font(FontTextHandlerType type) {
|
||||
inited = false;
|
||||
type = fontTypeName;
|
||||
this->type = fontTypeName;
|
||||
width = 400;
|
||||
size = 10;
|
||||
textHandler = NULL;
|
||||
|
||||
#ifdef USE_FTGL
|
||||
textHandler = new TextFTGL();
|
||||
metrics.setTextHandler(this->textHandler);
|
||||
|
||||
if(Font::forceLegacyFonts == false) {
|
||||
try {
|
||||
textHandler = NULL;
|
||||
textHandler = new TextFTGL(type);
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -119,12 +143,32 @@ Font::~Font() {
|
|||
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) {
|
||||
if(textHandler) {
|
||||
textHandler->init(typeGeneric,textHandler->GetFaceSize());
|
||||
try {
|
||||
this->type= typeGeneric;
|
||||
textHandler->init(typeGeneric,textHandler->GetFaceSize());
|
||||
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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->type= type;
|
||||
if(textHandler == NULL) {
|
||||
this->type= typeX11;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,15 +180,7 @@ int Font::getWidth() const {
|
|||
return width;
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class Font2D
|
||||
// ===============================================
|
||||
|
||||
Font2D::Font2D() {
|
||||
size = 10;
|
||||
}
|
||||
|
||||
int Font2D::getSize() const {
|
||||
int Font::getSize() const {
|
||||
if(textHandler) {
|
||||
return textHandler->GetFaceSize();
|
||||
}
|
||||
|
@ -152,7 +188,7 @@ int Font2D::getSize() const {
|
|||
return size;
|
||||
}
|
||||
}
|
||||
void Font2D::setSize(int size) {
|
||||
void Font::setSize(int size) {
|
||||
if(textHandler) {
|
||||
return textHandler->SetFaceSize(size);
|
||||
}
|
||||
|
@ -161,11 +197,18 @@ void Font2D::setSize(int size) {
|
|||
}
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class Font2D
|
||||
// ===============================================
|
||||
|
||||
Font2D::Font2D(FontTextHandlerType type) : Font(type) {
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class Font3D
|
||||
// ===============================================
|
||||
|
||||
Font3D::Font3D() {
|
||||
Font3D::Font3D(FontTextHandlerType type) : Font(type) {
|
||||
depth= 10.f;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@ using namespace std;
|
|||
std::string Text::DEFAULT_FONT_PATH = "";
|
||||
|
||||
//====================================================================
|
||||
Text::Text() {}
|
||||
Text::Text(FontTextHandlerType type) {
|
||||
this->type = type;
|
||||
}
|
||||
Text::~Text() {}
|
||||
void Text::init(string fontName, int fontSize) {}
|
||||
void Text::Render(const char*, const int) {}
|
||||
|
|
|
@ -79,3 +79,19 @@ void Font3DGl::end() {
|
|||
}
|
||||
|
||||
}}}//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;
|
||||
}
|
||||
|
||||
}}
|
||||
|
|
|
@ -29,12 +29,11 @@ using namespace std;
|
|||
using namespace Shared::Util;
|
||||
using namespace Shared::PlatformCommon;
|
||||
|
||||
namespace Shared{ namespace Graphics{ namespace Gl{
|
||||
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/arphic/uming.ttc",0); // Chinese
|
||||
|
@ -56,7 +55,17 @@ TextFTGL::TextFTGL() {
|
|||
//ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
||||
|
||||
//ftFont = new FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
||||
ftFont = new FTGLPixmapFont(fontFile);
|
||||
if(type == ftht_2D) {
|
||||
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()) {
|
||||
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 FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc");
|
||||
|
||||
ftFont = new FTGLPixmapFont(fontFile);
|
||||
if(type == ftht_2D) {
|
||||
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()) {
|
||||
printf("FTGL: error loading font: %s\n", fontFile);
|
||||
|
|
|
@ -28,16 +28,33 @@ namespace Shared { namespace Graphics { namespace Gl {
|
|||
TextRenderer2DGl::TextRenderer2DGl() {
|
||||
rendering= false;
|
||||
this->font = NULL;
|
||||
|
||||
//font3D = NULL;
|
||||
//tester = new TextRenderer3DGl();
|
||||
}
|
||||
|
||||
TextRenderer2DGl::~TextRenderer2DGl() {
|
||||
//delete font3D;
|
||||
//font3D = NULL;
|
||||
|
||||
//delete tester;
|
||||
//tester = NULL;
|
||||
}
|
||||
|
||||
void TextRenderer2DGl::begin(Font2D *font) {
|
||||
assert(!rendering);
|
||||
|
||||
rendering = true;
|
||||
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//
|
||||
|
@ -56,6 +73,9 @@ void TextRenderer2DGl::begin(Font2D *font) {
|
|||
// Widen an individual character
|
||||
|
||||
void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, Vec3f *color) {
|
||||
//tester->render(text, x, y, this->font->getWidth(),centered);
|
||||
//return;
|
||||
|
||||
assert(rendering);
|
||||
|
||||
assertGl();
|
||||
|
@ -68,7 +88,7 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V
|
|||
int line = 0;
|
||||
int size = font->getSize();
|
||||
const unsigned char *utext = NULL;
|
||||
FontMetrics *metrics = NULL;
|
||||
FontMetrics *metrics = NULL;
|
||||
|
||||
//printf("font->getTextHandler() [%p] centered = %d text [%s]\n",font->getTextHandler(),centered,text.c_str());
|
||||
|
||||
|
@ -76,11 +96,11 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V
|
|||
if(font->getTextHandler() != NULL) {
|
||||
if(centered) {
|
||||
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 {
|
||||
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 {
|
||||
|
@ -96,6 +116,9 @@ void TextRenderer2DGl::render(const string &text, int x, int y, bool centered, V
|
|||
}
|
||||
glRasterPos2f(rasterPos.x, rasterPos.y);
|
||||
|
||||
//font->getTextHandler()->Render("Zurück");
|
||||
//return;
|
||||
|
||||
if(Font::fontIsMultibyte == true) {
|
||||
if(font->getTextHandler() != NULL) {
|
||||
//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!
|
||||
|
||||
|
||||
|
||||
// This works
|
||||
//fontFTGL->Render(text.c_str());
|
||||
|
||||
|
||||
if(text.find("\n") == text.npos && text.find("\t") == text.npos) {
|
||||
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() {
|
||||
//tester->end();
|
||||
//return;
|
||||
|
||||
assert(rendering);
|
||||
rendering= false;
|
||||
}
|
||||
|
@ -341,7 +364,7 @@ void TextRenderer3DGl::begin(Font3D *font) {
|
|||
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);
|
||||
|
||||
const unsigned char *utext= NULL;
|
||||
|
@ -350,13 +373,17 @@ void TextRenderer3DGl::render(const string &text, float x, float y, float size,
|
|||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
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;
|
||||
|
||||
if(font->getTextHandler() != NULL) {
|
||||
if(centered) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
glScalef(scale, scale, scale);
|
||||
|
||||
font->getTextHandler()->Render(text.c_str());
|
||||
|
||||
/*
|
||||
if(Font::fontIsMultibyte == true) {
|
||||
if(font->getTextHandler() != NULL) {
|
||||
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();
|
||||
glPopAttrib();
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "randomgen.h"
|
||||
#include <algorithm>
|
||||
#include "platform_util.h"
|
||||
#include "utf8.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
|
@ -1934,6 +1935,33 @@ void copyFileTo(string fromFileName, string toFileName) {
|
|||
#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
|
||||
// =====================================
|
||||
|
|
|
@ -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());
|
||||
printf("About to try font [%s]\n",type.c_str());
|
||||
|
||||
XFontStruct* fontInfo = XLoadQueryFont(display, type.c_str());
|
||||
if(fontInfo == NULL) {
|
||||
string default_font = FontGl::getDefault_fontType();
|
||||
|
||||
//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());
|
||||
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());
|
||||
if(fontInfo == NULL) {
|
||||
|
|
|
@ -27,11 +27,11 @@ namespace Shared{ namespace Util{
|
|||
|
||||
const int strSize = 256;
|
||||
|
||||
bool strToBool(const string &s){
|
||||
if (s=="0" || s=="false"){
|
||||
bool strToBool(const string &s) {
|
||||
if(s=="0" || s=="false") {
|
||||
return false;
|
||||
}
|
||||
if (s=="1" || s=="true"){
|
||||
if(s=="1" || s=="true") {
|
||||
return true;
|
||||
}
|
||||
throw runtime_error("Error converting string to bool, expected 0 or 1, found: [" + s + "]");
|
||||
|
|
|
@ -25,11 +25,21 @@
|
|||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
#include "utf8.h"
|
||||
#include "font.h"
|
||||
|
||||
//#include <locale>
|
||||
//#include <iostream>
|
||||
//#include <string>
|
||||
//#include <sstream>
|
||||
#include "string_utils.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::PlatformCommon;
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
namespace Shared{ namespace Util{
|
||||
|
||||
|
@ -39,42 +49,329 @@ string Properties::applicationPath = "";
|
|||
// 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) {
|
||||
|
||||
//wchar_t lineBuffer[maxLine]=L"";
|
||||
char lineBuffer[maxLine]="";
|
||||
string line, key, value;
|
||||
size_t pos=0;
|
||||
this->path= path;
|
||||
|
||||
//std::locale::global(std::locale(""));
|
||||
bool is_utf8_language = valid_utf8_file(path.c_str());
|
||||
|
||||
#if defined(WIN32) && !defined(__MINGW32__)
|
||||
wstring wstr = utf8_decode(path);
|
||||
FILE *fp = _wfopen(wstr.c_str(), L"r");
|
||||
//wifstream fileStream(fp);
|
||||
ifstream fileStream(fp);
|
||||
#else
|
||||
//wifstream fileStream;
|
||||
ifstream fileStream;
|
||||
fileStream.open(path.c_str(), ios_base::in);
|
||||
#endif
|
||||
|
||||
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());
|
||||
throw runtime_error("Can't open propertyMap file: " + path);
|
||||
throw runtime_error("File NOT FOUND, can't open file: [" + path + "]");
|
||||
}
|
||||
|
||||
if(clearCurrentProperties == true) {
|
||||
propertyMap.clear();
|
||||
}
|
||||
while(!fileStream.eof()){
|
||||
|
||||
while(fileStream.eof() == false) {
|
||||
lineBuffer[0]='\0';
|
||||
fileStream.getline(lineBuffer, maxLine);
|
||||
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
|
||||
if(lineBuffer[0]!=';'){
|
||||
if(lineBuffer[0] != ';') {
|
||||
//wstring wstr = lineBuffer;
|
||||
//line.assign(wstr.begin(),wstr.end());
|
||||
|
||||
// gracefully handle win32 \r\n line endings
|
||||
size_t len= strlen(lineBuffer);
|
||||
if(len > 0 && lineBuffer[len-1] == '\r'){
|
||||
lineBuffer[len-1]= 0;
|
||||
if(len > 0 && lineBuffer[len-1] == '\r') {
|
||||
lineBuffer[len-1]= 0;
|
||||
}
|
||||
|
||||
line= lineBuffer;
|
||||
|
|
|
@ -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