String.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Graphics/String.hpp>
00029 #include <SFML/Graphics/FontManager.hpp>
00030 #include <SFML/Graphics/Image.hpp>
00031 #include <SFML/Graphics/OpenGL.hpp>
00032 #include <locale>
00033 
00034 
00035 namespace sf
00036 {
00040 String::String(const std::string& Text, const std::string& Font, float Size) :
00041 myFont(Font),
00042 mySize(Size)
00043 {
00044     SetText(Text);
00045 }
00046 
00047 
00051 String::String(const std::wstring& Text, const std::string& Font, float Size) :
00052 myText(Text),
00053 myFont(Font),
00054 mySize(Size)
00055 {
00056 
00057 }
00058 
00059 
00063 void String::PreloadFont(const std::string& Font, float Char, std::wstring Charset)
00064 {
00065     // Requesting the font will make the font manager create it
00066     priv::FontManager::GetInstance().GetBitmapFont(Font, static_cast<unsigned int>(Char), Charset);
00067 }
00068 
00069 
00073 void String::SetText(const std::string& Text)
00074 {
00075     if (!Text.empty())
00076     {
00077         std::vector<wchar_t> Buffer(Text.size());
00078         std::locale Locale("");
00079         std::use_facet<std::ctype<wchar_t> >(Locale).widen(Text.data(), Text.data() + Text.size(), &Buffer[0]);
00080 
00081         myText.assign(&Buffer[0], Buffer.size());
00082     }
00083     else
00084     {
00085         myText = L"";
00086     }
00087 }
00088 
00089 
00093 void String::SetText(const std::wstring& Text)
00094 {
00095     myText = Text;
00096 }
00097 
00098 
00102 void String::SetFont(const std::string& Font)
00103 {
00104     myFont = Font;
00105 }
00106 
00107 
00111 void String::SetSize(float Size)
00112 {
00113     mySize = Size;
00114 }
00115 
00116 
00120 const std::wstring& String::GetText() const
00121 {
00122     return myText;
00123 }
00124 
00125 
00129 const std::string& String::GetFont() const
00130 {
00131     return myFont;
00132 }
00133 
00134 
00138 float String::GetSize() const
00139 {
00140     return mySize;
00141 }
00142 
00143 
00147 FloatRect String::GetRect() const
00148 {
00149     // Get the bitmap font from the font manager
00150     const priv::FontManager::Font& BitmapFont = priv::FontManager::GetInstance().GetBitmapFont(myFont, static_cast<unsigned int>(mySize));
00151 
00152     // Initial values
00153     float CurWidth = 0;
00154     float Width    = 0;
00155     float Height   = mySize;
00156 
00157     // Go through each character
00158     for (std::size_t i = 0; i < myText.size(); ++i)
00159     {
00160         // Get the current character
00161         wchar_t c = myText[i];
00162 
00163         // Check if the character is in the charset
00164         std::map<wchar_t, priv::FontManager::Font::Character>::const_iterator It = BitmapFont.Characters.find(c);
00165         if (It == BitmapFont.Characters.end())
00166         {
00167             // No : add a space and continue to the next character
00168             CurWidth += mySize;
00169             continue;
00170         }
00171         const priv::FontManager::Font::Character& CurChar = It->second;
00172 
00173         // Get the dimensions of the current character from the font description
00174         const float Advance = CurChar.Advance * mySize / BitmapFont.CharSize;
00175 
00176         // Handle special characters...
00177         switch (c)
00178         {
00179             case L' ' :  CurWidth += Advance;    continue;
00180             case L'\t' : CurWidth += mySize * 4; continue;
00181             case L'\v' : Height   += mySize * 4; continue;
00182 
00183             case L'\n' :
00184                 Height += mySize;
00185                 if (CurWidth > Width) Width = CurWidth;
00186                 CurWidth = 0;
00187                 continue;
00188         }
00189 
00190         // Advance to the next character
00191         CurWidth += Advance;
00192     }
00193 
00194     // In case there was no '\n' in the string
00195     if (Width < 1)
00196         Width = CurWidth;
00197 
00198     return FloatRect(GetLeft(), GetTop(), GetLeft() + Width, GetTop() + Height);
00199 }
00200 
00201 
00205 void String::Render(RenderWindow&)
00206 {
00207     // No text, no rendering :)
00208     if (myText.empty())
00209         return;
00210 
00211     // Get the bitmap font from the font manager
00212     const priv::FontManager::Font& BitmapFont = priv::FontManager::GetInstance().GetBitmapFont(myFont, static_cast<unsigned int>(mySize));
00213 
00214     // Set the scaling factor to get the actual size
00215     float FactorX = GetScaleX() * mySize / BitmapFont.CharSize;
00216     float FactorY = GetScaleY() * mySize / BitmapFont.CharSize;
00217     GLCheck(glScalef(FactorX, FactorY, 1.f));
00218 
00219     // Bind the font texture
00220     BitmapFont.Texture.Bind();
00221 
00222     float X = 0;
00223     float Y = 0;
00224 
00225     // Draw the sprite
00226     glBegin(GL_QUADS);
00227     for (std::size_t i = 0; i < myText.size(); ++i)
00228     {
00229         // Get the current character
00230         wchar_t c = myText[i];
00231 
00232         // Check if the character is in the charset
00233         std::map<wchar_t, priv::FontManager::Font::Character>::const_iterator It = BitmapFont.Characters.find(c);
00234         if (It == BitmapFont.Characters.end())
00235         {
00236             // No : add a space and continue to the next character
00237             X += mySize;
00238             continue;
00239         }
00240         const priv::FontManager::Font::Character& CurChar = It->second;
00241 
00242         // Get the dimensions of the current character from font description
00243         const IntRect&   Rect       = CurChar.Rect;
00244         const FloatRect& Coord      = CurChar.Coord;
00245         const unsigned int AdvanceX = CurChar.Advance;
00246         const unsigned int AdvanceY = BitmapFont.CharSize;
00247 
00248         // Handle special characters
00249         switch (c)
00250         {
00251             case L' ' :  X += AdvanceX;        continue;
00252             case L'\n' : Y += AdvanceY; X = 0; continue;
00253             case L'\t' : X += AdvanceX * 4;    continue;
00254             case L'\v' : Y += AdvanceY * 4;    continue;
00255         }
00256 
00257         // Draw a textured quad for the current character
00258         glTexCoord2f(Coord.Left,  Coord.Top);    glVertex2f(X + Rect.Left,  Y + Rect.Top    + AdvanceY);
00259         glTexCoord2f(Coord.Left,  Coord.Bottom); glVertex2f(X + Rect.Left,  Y + Rect.Bottom + AdvanceY);
00260         glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + Rect.Right, Y + Rect.Bottom + AdvanceY);
00261         glTexCoord2f(Coord.Right, Coord.Top);    glVertex2f(X + Rect.Right, Y + Rect.Top    + AdvanceY);
00262 
00263         // Advance to the next character
00264         X += AdvanceX;
00265     }
00266     glEnd();
00267 }
00268 
00269 } // namespace sf