FS#90 - Improve Unicode string classes

Added the sf::String class to replace (and enhance) sf::Unicode::Text
FS#138 - Rename sf::String to sf::Text


git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1286 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
LaurentGom 2009-11-26 08:07:38 +00:00
parent 9f063921c9
commit 78247bd386
46 changed files with 3003 additions and 1725 deletions

View file

@ -71,26 +71,25 @@ myCharSize(0)
////////////////////////////////////////////////////////////
/// Load the font from a file
////////////////////////////////////////////////////////////
bool Font::LoadFromFile(const std::string& filename, unsigned int charSize, const Unicode::Text& charset)
bool Font::LoadFromFile(const std::string& filename, unsigned int charSize, String charset)
{
// Clear the previous character map
myGlyphs.clear();
// Always add these special characters
Unicode::UTF32String UTFCharset = charset;
if (UTFCharset.find(L' ') != Unicode::UTF32String::npos) UTFCharset += L' ';
if (UTFCharset.find(L'\n') != Unicode::UTF32String::npos) UTFCharset += L'\n';
if (UTFCharset.find(L'\v') != Unicode::UTF32String::npos) UTFCharset += L'\v';
if (UTFCharset.find(L'\t') != Unicode::UTF32String::npos) UTFCharset += L'\t';
if (std::find(charset.Begin(), charset.End(), L' ') == charset.End()) charset += L' ';
if (std::find(charset.Begin(), charset.End(), L'\n') == charset.End()) charset += L'\n';
if (std::find(charset.Begin(), charset.End(), L'\v') == charset.End()) charset += L'\v';
if (std::find(charset.Begin(), charset.End(), L'\t') == charset.End()) charset += L'\t';
return priv::FontLoader::GetInstance().LoadFontFromFile(filename, charSize, UTFCharset, *this);
return priv::FontLoader::GetInstance().LoadFontFromFile(filename, charSize, charset, *this);
}
////////////////////////////////////////////////////////////
/// Load the font from a file in memory
////////////////////////////////////////////////////////////
bool Font::LoadFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const Unicode::Text& charset)
bool Font::LoadFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, String charset)
{
// Clear the previous character map
myGlyphs.clear();
@ -103,13 +102,12 @@ bool Font::LoadFromMemory(const char* data, std::size_t sizeInBytes, unsigned in
}
// Always add these special characters
Unicode::UTF32String UTFCharset = charset;
if (UTFCharset.find(L' ') != Unicode::UTF32String::npos) UTFCharset += L' ';
if (UTFCharset.find(L'\n') != Unicode::UTF32String::npos) UTFCharset += L'\n';
if (UTFCharset.find(L'\v') != Unicode::UTF32String::npos) UTFCharset += L'\v';
if (UTFCharset.find(L'\t') != Unicode::UTF32String::npos) UTFCharset += L'\t';
if (std::find(charset.Begin(), charset.End(), L' ') == charset.End()) charset += L' ';
if (std::find(charset.Begin(), charset.End(), L'\n') == charset.End()) charset += L'\n';
if (std::find(charset.Begin(), charset.End(), L'\v') == charset.End()) charset += L'\v';
if (std::find(charset.Begin(), charset.End(), L'\t') == charset.End()) charset += L'\t';
return priv::FontLoader::GetInstance().LoadFontFromMemory(data, sizeInBytes, charSize, UTFCharset, *this);
return priv::FontLoader::GetInstance().LoadFontFromMemory(data, sizeInBytes, charSize, charset, *this);
}
@ -158,21 +156,22 @@ const Image& Font::GetImage() const
////////////////////////////////////////////////////////////
const Font& Font::GetDefaultFont()
{
static Font defaultFont;
static bool defaultFontLoaded = false;
static const char defaultFontData[] =
{
#include <SFML/Graphics/Arial.hpp>
};
static Font font;
static bool loaded = false;
// Load the default font on first call
if (!defaultFontLoaded)
if (!loaded)
{
defaultFont.LoadFromMemory(defaultFontData, sizeof(defaultFontData), 30);
defaultFontLoaded = true;
static const char data[] =
{
#include <SFML/Graphics/Arial.hpp>
};
font.LoadFromMemory(data, sizeof(data), 30);
loaded = true;
}
return defaultFont;
return font;
}
} // namespace sf

View file

@ -98,7 +98,7 @@ FontLoader::~FontLoader()
////////////////////////////////////////////////////////////
/// Load a font from a file
////////////////////////////////////////////////////////////
bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int charSize, const Unicode::UTF32String& charset, Font& font)
bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int charSize, const String& charset, Font& font)
{
// Check if Freetype is correctly initialized
if (!myLibrary)
@ -131,7 +131,7 @@ bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int char
////////////////////////////////////////////////////////////
/// Load the font from a file in memory
////////////////////////////////////////////////////////////
bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const Unicode::UTF32String& charset, Font& font)
bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const String& charset, Font& font)
{
// Check if Freetype is correctly initialized
if (!myLibrary)
@ -164,12 +164,12 @@ bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, u
////////////////////////////////////////////////////////////
/// Create a bitmap font from a font face and a characters set
////////////////////////////////////////////////////////////
FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const Unicode::UTF32String& charset, Font& font)
FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const String& charset, Font& font)
{
// Let's find how many characters to put in each row to make them fit into a squared texture
GLint maxSize;
GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize));
int nbChars = static_cast<int>(sqrt(static_cast<double>(charset.length())) * 0.75);
int nbChars = static_cast<int>(sqrt(static_cast<double>(charset.GetSize())) * 0.75);
// Clamp the character size to make sure we won't create a texture too big
if (nbChars * charSize >= static_cast<unsigned int>(maxSize))
@ -198,7 +198,7 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const
// Render all glyphs and sort them by size to optimize texture space
typedef std::multimap<FT_BitmapGlyph, Uint32, SizeCompare> GlyphTable;
GlyphTable glyphs;
for (std::size_t i = 0; i < charset.length(); ++i)
for (std::size_t i = 0; i < charset.GetSize(); ++i)
{
// Load the glyph corresponding to the current character
error = FT_Load_Char(face, charset[i], FT_LOAD_TARGET_NORMAL);
@ -293,7 +293,7 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const
font.myTexture.LoadFromPixels(texWidth, texHeight, &glyphsBuffer[0]);
// Now that the texture is created, we can precompute texture coordinates
for (std::size_t i = 0; i < charset.size(); ++i)
for (std::size_t i = 0; i < charset.GetSize(); ++i)
{
Uint32 curChar = charset[i];
font.myGlyphs[curChar].TexCoords = font.myTexture.GetTexCoords(coords[curChar]);
@ -491,7 +491,7 @@ FontLoader::~FontLoader()
////////////////////////////////////////////////////////////
/// Load a font from a file
////////////////////////////////////////////////////////////
bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int charSize, const Unicode::UTF32String& charset, Font& font)
bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int charSize, const String& charset, Font& font)
{
// Get the contents of the font file
std::ifstream file(filename.c_str(), std::ios_base::binary);
@ -511,12 +511,12 @@ bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int char
////////////////////////////////////////////////////////////
/// Load the font from a file in memory
////////////////////////////////////////////////////////////
bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const Unicode::UTF32String& charset, Font& font)
bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const String& charset, Font& font)
{
// Let's find how many characters to put in each row to make them fit into a squared texture
GLint maxSize;
GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize));
int nbChars = static_cast<int>(sqrt(static_cast<double>(charset.length())) * 0.75);
int nbChars = static_cast<int>(sqrt(static_cast<double>(charset.GetSize())) * 0.75);
// Clamp the character size to make sure we won't create a texture too big
if (nbChars * charSize >= static_cast<unsigned int>(maxSize))
@ -544,7 +544,7 @@ bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, u
// Render all glyphs and sort them by size to optimize texture space
typedef std::multimap<Glyph, Uint32, SizeCompare> GlyphTable;
GlyphTable glyphs;
for (std::size_t i = 0; i < charset.length(); ++i)
for (std::size_t i = 0; i < charset.GetSize(); ++i)
{
// Load the glyph corresponding to the current character
int index = stbtt_FindGlyphIndex(&info, static_cast<int>(charset[i]));
@ -636,7 +636,7 @@ bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, u
font.myTexture.LoadFromPixels(texWidth, texHeight, &glyphsBuffer[0]);
// Now that the texture is created, we can precompute texture coordinates
for (std::size_t i = 0; i < charset.size(); ++i)
for (std::size_t i = 0; i < charset.GetSize(); ++i)
{
Uint32 curChar = charset[i];
font.myGlyphs[curChar].TexCoords = font.myTexture.GetTexCoords(coords[curChar]);
@ -652,7 +652,7 @@ bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, u
////////////////////////////////////////////////////////////
/// Create a bitmap font from a font face and a characters set
////////////////////////////////////////////////////////////
FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const Unicode::UTF32String& charset, Font& font)
FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const String& charset, Font& font)
{
return 0;
}

View file

@ -29,7 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Unicode.hpp>
#include <SFML/System/String.hpp>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <string>
@ -67,7 +67,7 @@ public :
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool LoadFontFromFile(const std::string& filename, unsigned int charSize, const Unicode::UTF32String& charset, Font& font);
bool LoadFontFromFile(const std::string& filename, unsigned int charSize, const String& charset, Font& font);
////////////////////////////////////////////////////////////
/// Load the font from a file in memory
@ -81,7 +81,7 @@ public :
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const Unicode::UTF32String& charset, Font& font);
bool LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const String& charset, Font& font);
private :
@ -106,7 +106,7 @@ private :
/// \param font : Font object to fill up
///
////////////////////////////////////////////////////////////
FT_Error CreateBitmapFont(FT_Face face, unsigned int charSize, const Unicode::UTF32String& charset, Font& font);
FT_Error CreateBitmapFont(FT_Face face, unsigned int charSize, const String& charset, Font& font);
////////////////////////////////////////////////////////////
/// Get a description from a FT error code

View file

@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/String.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/RenderQueue.hpp>
@ -35,7 +35,7 @@ namespace sf
////////////////////////////////////////////////////////////
/// Default constructor
////////////////////////////////////////////////////////////
String::String() :
Text::Text() :
myFont (&Font::GetDefaultFont()),
mySize (30.f),
myStyle (Regular),
@ -48,30 +48,30 @@ myNeedRectUpdate(true)
////////////////////////////////////////////////////////////
/// Construct the string from any kind of text
////////////////////////////////////////////////////////////
String::String(const Unicode::Text& text, const Font& font, float size) :
Text::Text(const String& string, const Font& font, float size) :
myFont (&font),
mySize (size),
myStyle (Regular),
myNeedRectUpdate(true)
{
SetText(text);
SetString(string);
}
////////////////////////////////////////////////////////////
/// Set the text (from any kind of string)
////////////////////////////////////////////////////////////
void String::SetText(const Unicode::Text& text)
void Text::SetString(const String& string)
{
myNeedRectUpdate = true;
myText = text;
myString = string;
}
////////////////////////////////////////////////////////////
/// Set the font of the string
////////////////////////////////////////////////////////////
void String::SetFont(const Font& font)
void Text::SetFont(const Font& font)
{
if (myFont != &font)
{
@ -84,7 +84,7 @@ void String::SetFont(const Font& font)
////////////////////////////////////////////////////////////
/// Set the size of the string
////////////////////////////////////////////////////////////
void String::SetSize(float size)
void Text::SetSize(float size)
{
if (mySize != size)
{
@ -98,7 +98,7 @@ void String::SetSize(float size)
/// Set the style of the text
/// The default style is Regular
////////////////////////////////////////////////////////////
void String::SetStyle(unsigned long style)
void Text::SetStyle(unsigned long style)
{
if (myStyle != style)
{
@ -111,16 +111,16 @@ void String::SetStyle(unsigned long style)
////////////////////////////////////////////////////////////
/// Get the text (the returned text can be converted implicitely to any kind of string)
////////////////////////////////////////////////////////////
const Unicode::Text& String::GetText() const
const String& Text::GetString() const
{
return myText;
return myString;
}
////////////////////////////////////////////////////////////
/// Get the font used by the string
////////////////////////////////////////////////////////////
const Font& String::GetFont() const
const Font& Text::GetFont() const
{
return *myFont;
}
@ -129,7 +129,7 @@ const Font& String::GetFont() const
////////////////////////////////////////////////////////////
/// Get the size of the characters
////////////////////////////////////////////////////////////
float String::GetSize() const
float Text::GetSize() const
{
return mySize;
}
@ -138,7 +138,7 @@ float String::GetSize() const
////////////////////////////////////////////////////////////
/// Get the style of the text
////////////////////////////////////////////////////////////
unsigned long String::GetStyle() const
unsigned long Text::GetStyle() const
{
return myStyle;
}
@ -149,14 +149,11 @@ unsigned long String::GetStyle() const
/// in coordinates relative to the string
/// (note : translation, center, rotation and scale are not applied)
////////////////////////////////////////////////////////////
sf::Vector2f String::GetCharacterPos(std::size_t index) const
sf::Vector2f Text::GetCharacterPos(std::size_t index) const
{
// First get the UTF32 representation of the text
const Unicode::UTF32String& text = myText;
// Adjust the index if it's out of range
if (index > text.length())
index = text.length();
if (index > myString.GetSize())
index = myString.GetSize();
// The final size is based on the text size
float factor = mySize / myFont->GetCharacterSize();
@ -167,7 +164,7 @@ sf::Vector2f String::GetCharacterPos(std::size_t index) const
for (std::size_t i = 0; i < index; ++i)
{
// Get the current character and its corresponding glyph
Uint32 curChar = text[i];
Uint32 curChar = myString[i];
const Glyph& curGlyph = myFont->GetGlyph(curChar);
float advanceX = curGlyph.Advance * factor;
@ -191,10 +188,10 @@ sf::Vector2f String::GetCharacterPos(std::size_t index) const
////////////////////////////////////////////////////////////
/// Get the string rectangle on screen
////////////////////////////////////////////////////////////
FloatRect String::GetRect() const
FloatRect Text::GetRect() const
{
if (myNeedRectUpdate)
const_cast<String*>(this)->RecomputeRect();
const_cast<Text*>(this)->RecomputeRect();
FloatRect rect;
rect.Left = (myBaseRect.Left - GetOrigin().x) * GetScale().x + GetPosition().x;
@ -209,13 +206,10 @@ FloatRect String::GetRect() const
////////////////////////////////////////////////////////////
/// /see sfDrawable::Render
////////////////////////////////////////////////////////////
void String::Render(RenderTarget&, RenderQueue& queue) const
void Text::Render(RenderTarget&, RenderQueue& queue) const
{
// First get the internal UTF-32 string of the text
const Unicode::UTF32String& text = myText;
// No text, no rendering :)
if (text.empty())
if (myString.IsEmpty())
return;
// Set the scaling factor to get the actual size
@ -239,10 +233,10 @@ void String::Render(RenderTarget&, RenderQueue& queue) const
// Draw one quad for each character
unsigned int index = 0;
queue.BeginBatch();
for (std::size_t i = 0; i < text.size(); ++i)
for (std::size_t i = 0; i < myString.GetSize(); ++i)
{
// Get the current character and its corresponding glyph
Uint32 curChar = text[i];
Uint32 curChar = myString[i];
const Glyph& curGlyph = myFont->GetGlyph(curChar);
int advance = curGlyph.Advance;
const IntRect& rect = curGlyph.Rectangle;
@ -294,10 +288,10 @@ void String::Render(RenderTarget&, RenderQueue& queue) const
y = charSize;
queue.BeginBatch();
for (std::size_t i = 0; i < text.size(); ++i)
for (std::size_t i = 0; i < myString.GetSize(); ++i)
{
// Get the current character and its corresponding glyph
Uint32 curChar = text[i];
Uint32 curChar = myString[i];
const Glyph& curGlyph = myFont->GetGlyph(curChar);
int advance = curGlyph.Advance;
const IntRect& rect = curGlyph.Rectangle;
@ -360,16 +354,13 @@ void String::Render(RenderTarget&, RenderQueue& queue) const
////////////////////////////////////////////////////////////
/// Recompute the bounding rectangle of the text
////////////////////////////////////////////////////////////
void String::RecomputeRect()
void Text::RecomputeRect()
{
// First get the internal UTF-32 string of the text
const Unicode::UTF32String& text = myText;
// Reset the "need update" state
myNeedRectUpdate = false;
// No text, empty box :)
if (text.empty())
if (myString.IsEmpty())
{
myBaseRect = FloatRect(0, 0, 0, 0);
return;
@ -383,10 +374,10 @@ void String::RecomputeRect()
float factor = mySize / myFont->GetCharacterSize();
// Go through each character
for (std::size_t i = 0; i < text.size(); ++i)
for (std::size_t i = 0; i < myString.GetSize(); ++i)
{
// Get the current character and its corresponding glyph
Uint32 curChar = text[i];
Uint32 curChar = myString[i];
const Glyph& curGlyph = myFont->GetGlyph(curChar);
float advance = curGlyph.Advance * factor;
const IntRect& rect = curGlyph.Rectangle;

387
src/SFML/System/String.cpp Normal file
View file

@ -0,0 +1,387 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/String.hpp>
#include <SFML/System/Utf.hpp>
#include <iterator>
#include <string.h>
namespace sf
{
////////////////////////////////////////////////////////////
String::String()
{
}
////////////////////////////////////////////////////////////
String::String(const char* ansiString)
{
if (ansiString)
{
std::size_t length = strlen(ansiString);
if (length > 0)
{
myString.reserve(length + 1);
Utf32::FromAnsi(ansiString, ansiString + length, std::back_inserter(myString));
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::string& ansiString)
{
myString.reserve(ansiString.length() + 1);
Utf32::FromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(myString));
}
////////////////////////////////////////////////////////////
String::String(const char* ansiString, const std::locale& locale)
{
if (ansiString)
{
std::size_t length = strlen(ansiString);
if (length > 0)
{
myString.reserve(length + 1);
Utf32::FromAnsi(ansiString, ansiString + length, std::back_inserter(myString), locale);
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::string& ansiString, const std::locale& locale)
{
myString.reserve(ansiString.length() + 1);
Utf32::FromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(myString), locale);
}
////////////////////////////////////////////////////////////
String::String(const wchar_t* wideString)
{
if (wideString)
{
std::size_t length = wcslen(wideString);
if (length > 0)
{
myString.reserve(length + 1);
Utf32::FromWide(wideString, wideString + length, std::back_inserter(myString));
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::wstring& wideString)
{
myString.reserve(wideString.length() + 1);
Utf32::FromWide(wideString.begin(), wideString.end(), std::back_inserter(myString));
}
////////////////////////////////////////////////////////////
String::String(const Uint32* utf32String)
{
if (utf32String)
myString = utf32String;
}
////////////////////////////////////////////////////////////
String::String(const std::basic_string<Uint32>& utf32String) :
myString(utf32String)
{
}
////////////////////////////////////////////////////////////
String::String(const String& copy) :
myString(copy.myString)
{
}
////////////////////////////////////////////////////////////
String::operator std::string() const
{
return ToAnsiString();
}
////////////////////////////////////////////////////////////
String::operator std::wstring() const
{
return ToWideString();
}
////////////////////////////////////////////////////////////
std::string String::ToAnsiString() const
{
// Prepare the output string
std::string output;
output.reserve(myString.length() + 1);
// Convert
Utf32::ToAnsi(myString.begin(), myString.end(), std::back_inserter(output), 0);
return output;
}
////////////////////////////////////////////////////////////
std::string String::ToAnsiString(const std::locale& locale) const
{
// Prepare the output string
std::string output;
output.reserve(myString.length() + 1);
// Convert
Utf32::ToAnsi(myString.begin(), myString.end(), std::back_inserter(output), 0, locale);
return output;
}
////////////////////////////////////////////////////////////
std::wstring String::ToWideString() const
{
// Prepare the output string
std::wstring output;
output.reserve(myString.length() + 1);
// Convert
Utf32::ToWide(myString.begin(), myString.end(), std::back_inserter(output), 0);
return output;
}
////////////////////////////////////////////////////////////
String& String::operator =(const String& right)
{
myString = right.myString;
return *this;
}
////////////////////////////////////////////////////////////
String& String::operator +=(char right)
{
myString += Utf32::DecodeAnsi(right);
return *this;
}
////////////////////////////////////////////////////////////
String& String::operator +=(wchar_t right)
{
myString += Utf32::DecodeWide(right);
return *this;
}
////////////////////////////////////////////////////////////
String& String::operator +=(Uint32 right)
{
myString += right;
return *this;
}
////////////////////////////////////////////////////////////
String& String::operator +=(const String& right)
{
myString += right.myString;
return *this;
}
////////////////////////////////////////////////////////////
Uint32 String::operator [](std::size_t index) const
{
return myString[index];
}
////////////////////////////////////////////////////////////
Uint32& String::operator [](std::size_t index)
{
return myString[index];
}
////////////////////////////////////////////////////////////
void String::Clear()
{
myString.clear();
}
////////////////////////////////////////////////////////////
std::size_t String::GetSize() const
{
return myString.size();
}
////////////////////////////////////////////////////////////
bool String::IsEmpty() const
{
return myString.empty();
}
////////////////////////////////////////////////////////////
void String::Erase(std::size_t position, std::size_t count)
{
myString.erase(position, count);
}
////////////////////////////////////////////////////////////
const Uint32* String::GetData() const
{
return myString.c_str();
}
////////////////////////////////////////////////////////////
String::Iterator String::Begin()
{
return myString.begin();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::Begin() const
{
return myString.begin();
}
////////////////////////////////////////////////////////////
String::Iterator String::End()
{
return myString.end();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::End() const
{
return myString.end();
}
////////////////////////////////////////////////////////////
bool operator ==(const String& left, const String& right)
{
return left.myString == right.myString;
}
////////////////////////////////////////////////////////////
bool operator !=(const String& left, const String& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const String& left, const String& right)
{
return left.myString < right.myString;
}
////////////////////////////////////////////////////////////
bool operator >(const String& left, const String& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const String& left, const String& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const String& left, const String& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
String operator +(const String& left, char right)
{
String string = left;
string += right;
return string;
}
////////////////////////////////////////////////////////////
String operator +(const String& left, wchar_t right)
{
String string = left;
string += right;
return string;
}
////////////////////////////////////////////////////////////
String operator +(const String& left, Uint32 right)
{
String string = left;
string += right;
return string;
}
////////////////////////////////////////////////////////////
String operator +(const String& left, const String& right)
{
String string = left;
string += right;
return string;
}
} // namespace sf

View file

@ -1,300 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Unicode.hpp>
#include <stdexcept>
#include <string.h>
////////////////////////////////////////////////////////////
// References :
//
// http://www.unicode.org/
// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
// http://people.w3.org/rishida/scripts/uniview/conversion
//
////////////////////////////////////////////////////////////
namespace
{
////////////////////////////////////////////////////////////
// Generic utility function to compute the number
// of characters in a null-terminated string of any type
////////////////////////////////////////////////////////////
template <typename T>
std::size_t StrLen(const T* Str)
{
std::size_t Length = 0;
while (*Str++) Length++;
return Length;
}
////////////////////////////////////////////////////////////
// Get the current system locale
////////////////////////////////////////////////////////////
std::locale GetCurrentLocale()
{
try
{
return std::locale("");
}
catch (std::runtime_error&)
{
// It seems some implementations don't know the "" locale
// (Mac OS, MinGW)
return std::locale();
}
}
}
namespace sf
{
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
const int Unicode::UTF8TrailingBytes[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
};
const Uint32 Unicode::UTF8Offsets[6] =
{
0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080
};
const Uint8 Unicode::UTF8FirstBytes[7] =
{
0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
};
////////////////////////////////////////////////////////////
/// Default constructor (empty text)
////////////////////////////////////////////////////////////
Unicode::Text::Text()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
/// Construct the unicode text from any type of string
////////////////////////////////////////////////////////////
Unicode::Text::Text(const char* Str)
{
if (Str)
{
std::size_t Length = StrLen(Str);
if (Length > 0)
{
myUTF32String.reserve(Length + 1);
Unicode::ANSIToUTF32(Str, Str + Length, std::back_inserter(myUTF32String));
}
}
}
Unicode::Text::Text(const wchar_t* Str)
{
if (Str)
{
std::size_t Length = StrLen(Str);
if (Length > 0)
{
// See comments below, in Unicode::Text::Text(const std::wstring&)
myUTF32String.reserve(Length + 1);
switch (sizeof(wchar_t))
{
case 2 : Unicode::UTF16ToUTF32(Str, Str + Length, std::back_inserter(myUTF32String), 0); break;
case 4 : std::copy(Str, Str + Length, std::back_inserter(myUTF32String)); break;
default : break;
}
}
}
}
Unicode::Text::Text(const Uint8* Str)
{
if (Str)
{
std::size_t Length = StrLen(Str);
if (Length > 0)
{
myUTF32String.reserve(Length + 1);
Unicode::UTF8ToUTF32(Str, Str + Length, std::back_inserter(myUTF32String), 0);
}
}
}
Unicode::Text::Text(const Uint16* Str)
{
if (Str)
{
std::size_t Length = StrLen(Str);
if (Length > 0)
{
myUTF32String.reserve(Length+ 1);
Unicode::UTF16ToUTF32(Str, Str + Length, std::back_inserter(myUTF32String), 0);
}
}
}
Unicode::Text::Text(const Uint32* Str)
{
if (Str)
myUTF32String = Str;
}
Unicode::Text::Text(const std::string& Str)
{
myUTF32String.reserve(Str.length() + 1);
Unicode::ANSIToUTF32(Str.begin(), Str.end(), std::back_inserter(myUTF32String));
}
Unicode::Text::Text(const std::wstring& Str)
{
// This function assumes that 2-byte large wchar_t are encoded in UTF-16 (Windows), and
// 4-byte large wchar_t are encoded using UTF-32 (Unix)
// Is that always true ? (some platforms may use JIS Japanese encoding)
// The macro __STDC_ISO_10646__ should help identifying UTF-32 compliant implementations
myUTF32String.reserve(Str.length() + 1);
// Select the proper function according to the (supposed) wchar_t system encoding
switch (sizeof(wchar_t))
{
// wchar_t uses UTF-16 -- need a conversion
case 2 :
{
Unicode::UTF16ToUTF32(Str.begin(), Str.end(), std::back_inserter(myUTF32String), 0);
break;
}
// wchar_t uses UTF-32 -- direct copy
case 4 :
{
std::copy(Str.begin(), Str.end(), std::back_inserter(myUTF32String));
break;
}
// This should never happen
default : break;
}
}
Unicode::Text::Text(const Unicode::UTF8String& Str)
{
myUTF32String.reserve(Str.length() + 1);
Unicode::UTF8ToUTF32(Str.begin(), Str.end(), std::back_inserter(myUTF32String), 0);
}
Unicode::Text::Text(const Unicode::UTF16String& Str)
{
myUTF32String.reserve(Str.length() + 1);
Unicode::UTF16ToUTF32(Str.begin(), Str.end(), std::back_inserter(myUTF32String), 0);
}
Unicode::Text::Text(const Unicode::UTF32String& Str)
{
myUTF32String = Str;
}
////////////////////////////////////////////////////////////
/// Operator to cast the text to any type of string
////////////////////////////////////////////////////////////
Unicode::Text::operator std::string() const
{
std::string Output;
Output.reserve(myUTF32String.length() + 1);
Unicode::UTF32ToANSI(myUTF32String.begin(), myUTF32String.end(), std::back_inserter(Output), 0, Unicode::GetDefaultLocale());
return Output;
}
Unicode::Text::operator std::wstring() const
{
// This function assumes that 2-byte large wchar_t are encoded in UTF-16 (Windows), and
// 4-byte large wchar_t are encoded using UTF-32 (Unix)
// Is that always true ? (some platforms may use JIS Japanese encoding)
// The macro __STDC_ISO_10646__ should help identifying UTF-32 compliant implementations
std::wstring Output;
Output.reserve(myUTF32String.length() + 1);
// Select the proper function according to the (supposed) wchar_t system encoding
switch (sizeof(wchar_t))
{
// wchar_t uses UTF-16 -- need a conversion
case 2 :
{
UTF32ToUTF16(myUTF32String.begin(), myUTF32String.end(), std::back_inserter(Output), 0);
break;
}
// wchar_t uses UTF-32 -- direct copy
case 4 :
{
std::copy(myUTF32String.begin(), myUTF32String.end(), std::back_inserter(Output));
break;
}
// This should never happen
default : break;
}
return Output;
}
Unicode::Text::operator sf::Unicode::UTF8String() const
{
Unicode::UTF8String Output;
Output.reserve(myUTF32String.length() * 4 + 1);
Unicode::UTF32ToUTF8(myUTF32String.begin(), myUTF32String.end(), std::back_inserter(Output), 0);
return Output;
}
Unicode::Text::operator sf::Unicode::UTF16String() const
{
Unicode::UTF16String Output;
Output.reserve(myUTF32String.length() * 2 + 1);
Unicode::UTF32ToUTF16(myUTF32String.begin(), myUTF32String.end(), std::back_inserter(Output), 0);
return Output;
}
Unicode::Text::operator const sf::Unicode::UTF32String&() const
{
return myUTF32String;
}
////////////////////////////////////////////////////////////
/// Get the default system locale
////////////////////////////////////////////////////////////
const std::locale& Unicode::GetDefaultLocale()
{
// It seems getting the default locale is a very expensive operation,
// so we only do it once and then store the locale for reuse.
// Warning : this code won't be aware of any change of the default locale during runtime
static std::locale DefaultLocale = GetCurrentLocale();
return DefaultLocale;
}
} // namespace sf

79
src/SFML/System/Utf.cpp Normal file
View file

@ -0,0 +1,79 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Utf.hpp>
#include <exception>
#include <string.h>
////////////////////////////////////////////////////////////
// References :
//
// http://www.unicode.org/
// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
// http://people.w3.org/rishida/scripts/uniview/conversion
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace
{
// Get the current global locale
std::locale GetCurrentLocale()
{
try
{
return std::locale("");
}
catch (std::exception&)
{
// It seems that some implementations don't know the "" locale (Mac OS X, MinGW)
return std::locale();
}
}
}
namespace sf
{
////////////////////////////////////////////////////////////
/// Get the default system locale
////////////////////////////////////////////////////////////
const std::locale& GetDefaultLocale()
{
// It seems that getting the default locale is a very expensive operation,
// so we only do it once and then store the locale for reuse.
// Warning: this code won't be aware of any change of the default locale during runtime.
static std::locale locale = GetCurrentLocale();
return locale;
}
} // namespace sf

View file

@ -698,14 +698,13 @@ bool WindowImplX11::ProcessEvent(XEvent windowEvent)
int length = Xutf8LookupString(myInputContext, &windowEvent.xkey, reinterpret_cast<char*>(keyBuffer), sizeof(keyBuffer), NULL, &status);
if (length > 0)
{
Uint32 unicode[2]; // just in case, but 1 character should be enough
const Uint32* end = Unicode::UTF8ToUTF32(keyBuffer, keyBuffer + length, unicode);
if (end > unicode)
Uint32 unicode = 0;
Utf8::Decode(keyBuffer, keyBuffer + length, unicode, 0);
if (unicode != 0)
{
Event textEvent;
textEvent.Type = Event::TextEntered;
textEvent.Text.Unicode = unicode[0];
textEvent.Text.Unicode = unicode;
SendEvent(textEvent);
}
}