summaryrefslogtreecommitdiff
path: root/src/SFML/Graphics/String.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Graphics/String.cpp')
-rwxr-xr-xsrc/SFML/Graphics/String.cpp316
1 files changed, 226 insertions, 90 deletions
diff --git a/src/SFML/Graphics/String.cpp b/src/SFML/Graphics/String.cpp
index c78fdd5..f3d0e25 100755
--- a/src/SFML/Graphics/String.cpp
+++ b/src/SFML/Graphics/String.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2008 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.
@@ -26,9 +26,8 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/String.hpp>
-#include <SFML/Graphics/FontManager.hpp>
#include <SFML/Graphics/Image.hpp>
-#include <SFML/Graphics/OpenGL.hpp>
+#include <SFML/Graphics/Renderer.hpp>
#include <locale>
@@ -37,10 +36,12 @@ namespace sf
////////////////////////////////////////////////////////////
/// Construct the string from a multibyte text
////////////////////////////////////////////////////////////
-String::String(const std::string& Text, const std::string& Font, float Size) :
-mySize(Size)
+String::String(const std::string& Text, const Font& CharFont, float Size) :
+mySize (Size),
+myStyle (Regular),
+myNeedRectUpdate(true)
{
- SetFont(Font);
+ SetFont(CharFont);
SetText(Text);
}
@@ -48,29 +49,23 @@ mySize(Size)
////////////////////////////////////////////////////////////
/// Construct the string from a unicode text
////////////////////////////////////////////////////////////
-String::String(const std::wstring& Text, const std::string& Font, float Size) :
-mySize(Size)
+String::String(const std::wstring& Text, const Font& CharFont, float Size) :
+mySize (Size),
+myStyle (Regular),
+myNeedRectUpdate(true)
{
- SetFont(Font);
+ SetFont(CharFont);
SetText(Text);
}
////////////////////////////////////////////////////////////
-/// Preload a bitmap font (otherwise, it is done the first time the font is drawn)
-////////////////////////////////////////////////////////////
-void String::PreloadFont(const std::string& Font, float Char, std::wstring Charset)
-{
- // Requesting the font will make the font manager create it
- priv::FontManager::GetInstance().GetBitmapFont(Font, static_cast<unsigned int>(Char), Charset);
-}
-
-
-////////////////////////////////////////////////////////////
/// Set the text (from a multibyte string)
////////////////////////////////////////////////////////////
void String::SetText(const std::string& Text)
{
+ myNeedRectUpdate = true;
+
if (!Text.empty())
{
std::vector<wchar_t> Buffer(Text.size());
@@ -97,6 +92,7 @@ void String::SetText(const std::string& Text)
////////////////////////////////////////////////////////////
void String::SetText(const std::wstring& Text)
{
+ myNeedRectUpdate = true;
myText = Text;
}
@@ -104,9 +100,13 @@ void String::SetText(const std::wstring& Text)
////////////////////////////////////////////////////////////
/// Set the font of the string
////////////////////////////////////////////////////////////
-void String::SetFont(const std::string& Font)
+void String::SetFont(const Font& CharFont)
{
- myFont = Font;
+ if (myFont != &CharFont)
+ {
+ myNeedRectUpdate = true;
+ myFont = &CharFont;
+ }
}
@@ -115,7 +115,25 @@ void String::SetFont(const std::string& Font)
////////////////////////////////////////////////////////////
void String::SetSize(float Size)
{
- mySize = Size;
+ if (mySize != Size)
+ {
+ myNeedRectUpdate = true;
+ mySize = Size;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Set the style of the text
+/// The default style is Regular
+////////////////////////////////////////////////////////////
+void String::SetStyle(unsigned long TextStyle)
+{
+ if (myStyle != TextStyle)
+ {
+ myNeedRectUpdate = true;
+ myStyle = TextStyle;
+ }
}
@@ -157,9 +175,9 @@ std::string String::GetText() const
////////////////////////////////////////////////////////////
/// Get the font used by the string
////////////////////////////////////////////////////////////
-const std::string& String::GetFont() const
+const Font& String::GetFont() const
{
- return myFont;
+ return *myFont;
}
@@ -173,128 +191,246 @@ float String::GetSize() const
////////////////////////////////////////////////////////////
+/// Get the style of the text
+////////////////////////////////////////////////////////////
+unsigned long String::GetStyle() const
+{
+ return myStyle;
+}
+
+
+////////////////////////////////////////////////////////////
/// Get the string rectangle on screen
////////////////////////////////////////////////////////////
FloatRect String::GetRect() const
{
- // Get the bitmap font from the font manager
- const priv::FontManager::Font& BitmapFont = priv::FontManager::GetInstance().GetBitmapFont(myFont, static_cast<unsigned int>(mySize));
+ if (myNeedRectUpdate)
+ const_cast<String*>(this)->RecomputeRect();
- // Initial values
- float CurWidth = 0;
- float Width = 0;
- float Height = mySize;
+ FloatRect Rect;
+ Rect.Left = (myBaseRect.Left - GetCenter().x) * GetScale().x + GetPosition().x;
+ Rect.Top = (myBaseRect.Top - GetCenter().y) * GetScale().y + GetPosition().y;
+ Rect.Right = (myBaseRect.Right - GetCenter().x) * GetScale().x + GetPosition().x;
+ Rect.Bottom = (myBaseRect.Bottom - GetCenter().y) * GetScale().y + GetPosition().y;
- // Go through each character
+ return Rect;
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see sfDrawable::Render
+////////////////////////////////////////////////////////////
+void String::Render(const RenderWindow&) const
+{
+ // No text, no rendering :)
+ if (myText.empty())
+ return;
+
+ // Set the scaling factor to get the actual size
+ float Factor = mySize / myFont->myCharSize;
+ GLCheck(glScalef(Factor, Factor, 1.f));
+
+ // Bind the font texture
+ myFont->myTexture.Bind();
+
+ // Initialize the rendering coordinates
+ float X = 0.f;
+ float Y = static_cast<float>(myFont->myCharSize);
+
+ // Holds the lines to draw later, for underlined style
+ std::vector<float> UnderlineCoords;
+ UnderlineCoords.reserve(16);
+
+ // Compute the shearing to apply if we're using the italic style
+ float ItalicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
+
+ // Draw one quad for each character
+ glBegin(GL_QUADS);
for (std::size_t i = 0; i < myText.size(); ++i)
{
// Get the current character
wchar_t c = myText[i];
// Check if the character is in the charset
- std::map<wchar_t, priv::FontManager::Font::Character>::const_iterator It = BitmapFont.Characters.find(c);
- if (It == BitmapFont.Characters.end())
+ std::map<wchar_t, Font::Character>::const_iterator It = myFont->myCharacters.find(c);
+ if (It == myFont->myCharacters.end())
{
// No : add a space and continue to the next character
- CurWidth += mySize;
+ X += myFont->myCharSize;
continue;
}
- const priv::FontManager::Font::Character& CurChar = It->second;
// Get the dimensions of the current character from the font description
- const float Advance = CurChar.Advance * mySize / BitmapFont.CharSize;
+ const Font::Character& CurChar = It->second;
+ const IntRect& Rect = CurChar.Rect;
+ const FloatRect& Coord = CurChar.Coord;
- // Handle special characters...
+ // If we're using the underlined style and there's a new line,
+ // we keep track of the previous line to draw it later
+ if ((c == L'\n') && (myStyle & Underlined))
+ {
+ UnderlineCoords.push_back(X);
+ UnderlineCoords.push_back(Y + 2);
+ }
+
+ // Handle special characters
switch (c)
{
- case L' ' : CurWidth += Advance; continue;
- case L'\t' : CurWidth += mySize * 4; continue;
- case L'\v' : Height += mySize * 4; continue;
+ case L' ' : X += CurChar.Advance; continue;
+ case L'\n' : Y += myFont->myCharSize; X = 0; continue;
+ case L'\t' : X += CurChar.Advance * 4; continue;
+ case L'\v' : Y += myFont->myCharSize * 4; continue;
+ }
- case L'\n' :
- Height += mySize;
- if (CurWidth > Width) Width = CurWidth;
- CurWidth = 0;
- continue;
+ // Draw a textured quad for the current character
+ glTexCoord2f(Coord.Left, Coord.Top); glVertex2f(X + Rect.Left - ItalicCoeff * Rect.Top, Y + Rect.Top);
+ glTexCoord2f(Coord.Left, Coord.Bottom); glVertex2f(X + Rect.Left - ItalicCoeff * Rect.Bottom, Y + Rect.Bottom);
+ glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + Rect.Right - ItalicCoeff * Rect.Bottom, Y + Rect.Bottom);
+ glTexCoord2f(Coord.Right, Coord.Top); glVertex2f(X + Rect.Right - ItalicCoeff * Rect.Top, Y + Rect.Top);
+
+ // If we're using the bold style, we must render the character 4 more times,
+ // slightly offseted, to simulate a higher weight
+ if (myStyle & Bold)
+ {
+ static const float OffsetsX[] = {-0.5f, 0.5f, 0.f, 0.f};
+ static const float OffsetsY[] = {0.f, 0.f, -0.5f, 0.5f};
+
+ for (int j = 0; j < 4; ++j)
+ {
+ glTexCoord2f(Coord.Left, Coord.Top); glVertex2f(X + OffsetsX[j] + Rect.Left - ItalicCoeff * Rect.Top, Y + OffsetsY[j] + Rect.Top);
+ glTexCoord2f(Coord.Left, Coord.Bottom); glVertex2f(X + OffsetsX[j] + Rect.Left - ItalicCoeff * Rect.Bottom, Y + OffsetsY[j] + Rect.Bottom);
+ glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + OffsetsX[j] + Rect.Right - ItalicCoeff * Rect.Bottom, Y + OffsetsY[j] + Rect.Bottom);
+ glTexCoord2f(Coord.Right, Coord.Top); glVertex2f(X + OffsetsX[j] + Rect.Right - ItalicCoeff * Rect.Top, Y + OffsetsY[j] + Rect.Top);
+ }
}
// Advance to the next character
- CurWidth += Advance;
+ X += CurChar.Advance;
}
+ glEnd();
- // In case there was no '\n' in the string
- if (Width < 1)
- Width = CurWidth;
+ // Draw the underlines if needed
+ if (myStyle & Underlined)
+ {
+ // Compute the line thickness
+ float Thickness = (myStyle & Bold) ? 3.f : 2.f;
+
+ // Add the last line (which was not finished with a \n)
+ UnderlineCoords.push_back(X);
+ UnderlineCoords.push_back(Y + 2);
- return FloatRect(GetLeft(), GetTop(), GetLeft() + Width, GetTop() + Height);
+ // Draw the underlines as quads
+ GLCheck(glDisable(GL_TEXTURE_2D));
+ glBegin(GL_QUADS);
+ for (std::size_t i = 0; i < UnderlineCoords.size(); i += 2)
+ {
+ glVertex2f(0, UnderlineCoords[i + 1]);
+ glVertex2f(0, UnderlineCoords[i + 1] + Thickness);
+ glVertex2f(UnderlineCoords[i], UnderlineCoords[i + 1] + Thickness);
+ glVertex2f(UnderlineCoords[i], UnderlineCoords[i + 1]);
+ }
+ glEnd();
+ }
}
////////////////////////////////////////////////////////////
-/// /see sfDrawable::Render
+/// Recompute the bounding rectangle of the text
////////////////////////////////////////////////////////////
-void String::Render(const RenderWindow&) const
+void String::RecomputeRect()
{
- // No text, no rendering :)
+ // Reset the "need update" state
+ myNeedRectUpdate = false;
+
+ // No text, empty box :)
if (myText.empty())
+ {
+ myBaseRect = FloatRect(0, 0, 0, 0);
return;
+ }
- // Get the bitmap font from the font manager
- const priv::FontManager::Font& BitmapFont = priv::FontManager::GetInstance().GetBitmapFont(myFont, static_cast<unsigned int>(mySize));
-
- // Set the scaling factor to get the actual size
- float FactorX = GetScaleX() * mySize / BitmapFont.CharSize;
- float FactorY = GetScaleY() * mySize / BitmapFont.CharSize;
- GLCheck(glScalef(FactorX, FactorY, 1.f));
-
- // Bind the font texture
- BitmapFont.Texture.Bind();
-
- float X = 0;
- float Y = 0;
+ // Initial values
+ float CurWidth = 0;
+ float CurHeight = 0;
+ float Width = 0;
+ float Height = 0;
+ float Factor = mySize / myFont->myCharSize;
- // Draw the sprite
- glBegin(GL_QUADS);
+ // Go through each character
for (std::size_t i = 0; i < myText.size(); ++i)
{
// Get the current character
wchar_t c = myText[i];
// Check if the character is in the charset
- std::map<wchar_t, priv::FontManager::Font::Character>::const_iterator It = BitmapFont.Characters.find(c);
- if (It == BitmapFont.Characters.end())
+ std::map<wchar_t, Font::Character>::const_iterator It = myFont->myCharacters.find(c);
+ if (It == myFont->myCharacters.end())
{
// No : add a space and continue to the next character
- X += mySize;
+ CurWidth += mySize;
continue;
}
- const priv::FontManager::Font::Character& CurChar = It->second;
- // Get the dimensions of the current character from font description
- const IntRect& Rect = CurChar.Rect;
- const FloatRect& Coord = CurChar.Coord;
- const unsigned int AdvanceX = CurChar.Advance;
- const unsigned int AdvanceY = BitmapFont.CharSize;
+ // Get the dimensions of the current character from the font description
+ const Font::Character& CurChar = It->second;
+ const IntRect& Rect = CurChar.Rect;
+ float Advance = CurChar.Advance * Factor;
- // Handle special characters
+ // Handle special characters...
switch (c)
{
- case L' ' : X += AdvanceX; continue;
- case L'\n' : Y += AdvanceY; X = 0; continue;
- case L'\t' : X += AdvanceX * 4; continue;
- case L'\v' : Y += AdvanceY * 4; continue;
- }
+ case L' ' : CurWidth += Advance; continue;
+ case L'\t' : CurWidth += mySize * 4; continue;
+ case L'\v' : Height += mySize * 4; CurHeight = 0; continue;
- // Draw a textured quad for the current character
- glTexCoord2f(Coord.Left, Coord.Top); glVertex2f(X + Rect.Left, Y + Rect.Top + AdvanceY);
- glTexCoord2f(Coord.Left, Coord.Bottom); glVertex2f(X + Rect.Left, Y + Rect.Bottom + AdvanceY);
- glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + Rect.Right, Y + Rect.Bottom + AdvanceY);
- glTexCoord2f(Coord.Right, Coord.Top); glVertex2f(X + Rect.Right, Y + Rect.Top + AdvanceY);
+ case L'\n' :
+ Height += mySize;
+ CurHeight = 0;
+ if (CurWidth > Width)
+ Width = CurWidth;
+ CurWidth = 0;
+ continue;
+ }
// Advance to the next character
- X += AdvanceX;
+ CurWidth += Advance;
+
+ // Update the maximum height
+ float CharHeight = (myFont->myCharSize + Rect.Bottom) * Factor;
+ if (CharHeight > CurHeight)
+ CurHeight = CharHeight;
}
- glEnd();
+
+ // Update the last line
+ if (CurWidth > Width)
+ Width = CurWidth;
+ Height += CurHeight;
+
+ // Add a slight width / height if we're using the bold style
+ if (myStyle & Bold)
+ {
+ Width += 1 * Factor;
+ Height += 1 * Factor;
+ }
+
+ // Add a slight width if we're using the italic style
+ if (myStyle & Italic)
+ {
+ Width += 0.208f * mySize;
+ }
+
+ // Add a slight height if we're using the underlined style
+ if (myStyle & Underlined)
+ {
+ if (CurHeight < mySize + 4 * Factor)
+ Height += 4 * Factor;
+ }
+
+ // Finally update the rectangle
+ myBaseRect.Left = 0;
+ myBaseRect.Top = 0;
+ myBaseRect.Right = Width;
+ myBaseRect.Bottom = Height;
}
} // namespace sf