String.cpp
1 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 // you must not claim that you wrote the original software.
15 // If you use this software in a product, an acknowledgment
16 // in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 // and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
24 
26 // Headers
28 #include <SFML/Graphics/String.hpp>
29 #include <SFML/Graphics/Image.hpp>
30 #include <SFML/Graphics/GraphicsContext.hpp>
31 #include <locale>
32 
33 
34 namespace sf
35 {
40 myFont (&Font::GetDefaultFont()),
41 mySize (30.f),
42 myStyle (Regular),
43 myNeedRectUpdate(true)
44 {
45 
46 }
47 
48 
52 String::String(const Unicode::Text& Text, const Font& CharFont, float Size) :
53 myFont (&CharFont),
54 mySize (Size),
55 myStyle (Regular),
56 myNeedRectUpdate(true)
57 {
58  SetText(Text);
59 }
60 
61 
65 void String::SetText(const Unicode::Text& Text)
66 {
67  myNeedRectUpdate = true;
68  myText = Text;
69 }
70 
71 
75 void String::SetFont(const Font& CharFont)
76 {
77  if (myFont != &CharFont)
78  {
79  myNeedRectUpdate = true;
80  myFont = &CharFont;
81  }
82 }
83 
84 
88 void String::SetSize(float Size)
89 {
90  if (mySize != Size)
91  {
92  myNeedRectUpdate = true;
93  mySize = Size;
94  }
95 }
96 
97 
102 void String::SetStyle(unsigned long TextStyle)
103 {
104  if (myStyle != TextStyle)
105  {
106  myNeedRectUpdate = true;
107  myStyle = TextStyle;
108  }
109 }
110 
111 
116 {
117  return myText;
118 }
119 
120 
124 const Font& String::GetFont() const
125 {
126  return *myFont;
127 }
128 
129 
133 float String::GetSize() const
134 {
135  return mySize;
136 }
137 
138 
142 unsigned long String::GetStyle() const
143 {
144  return myStyle;
145 }
146 
147 
153 sf::Vector2f String::GetCharacterPos(std::size_t Index) const
154 {
155  // First get the UTF32 representation of the text
156  const Unicode::UTF32String& Text = myText;
157 
158  // Adjust the index if it's out of range
159  if (Index > Text.length())
160  Index = Text.length();
161 
162  // The final size is based on the text size
163  float FactorX = mySize / myFont->GetCharacterSize();
164  float AdvanceY = mySize;
165 
166  // Compute the position
167  sf::Vector2f Position;
168  for (std::size_t i = 0; i < Index; ++i)
169  {
170  // Get the current character and its corresponding glyph
171  Uint32 CurChar = Text[i];
172  const Glyph& CurGlyph = myFont->GetGlyph(CurChar);
173  float AdvanceX = CurGlyph.Advance * FactorX;
174 
175  switch (CurChar)
176  {
177  // Handle special characters
178  case L' ' : Position.x += AdvanceX; break;
179  case L'\t' : Position.x += AdvanceX * 4; break;
180  case L'\v' : Position.y += AdvanceY * 4; break;
181  case L'\n' : Position.y += AdvanceY; Position.x = 0; break;
182 
183  // Regular character : just add its advance value
184  default : Position.x += AdvanceX; break;
185  }
186  }
187 
188  return Position;
189 }
190 
191 
196 {
197  if (myNeedRectUpdate)
198  const_cast<String*>(this)->RecomputeRect();
199 
200  FloatRect Rect;
201  Rect.Left = (myBaseRect.Left - GetCenter().x) * GetScale().x + GetPosition().x;
202  Rect.Top = (myBaseRect.Top - GetCenter().y) * GetScale().y + GetPosition().y;
203  Rect.Right = (myBaseRect.Right - GetCenter().x) * GetScale().x + GetPosition().x;
204  Rect.Bottom = (myBaseRect.Bottom - GetCenter().y) * GetScale().y + GetPosition().y;
205 
206  return Rect;
207 }
208 
209 
214 {
215  // First get the internal UTF-32 string of the text
216  const Unicode::UTF32String& Text = myText;
217 
218  // No text, no rendering :)
219  if (Text.empty())
220  return;
221 
222  // Set the scaling factor to get the actual size
223  float CharSize = static_cast<float>(myFont->GetCharacterSize());
224  float Factor = mySize / CharSize;
225  GLCheck(glScalef(Factor, Factor, 1.f));
226 
227  // Bind the font texture
228  myFont->GetImage().Bind();
229 
230  // Initialize the rendering coordinates
231  float X = 0.f;
232  float Y = CharSize;
233 
234  // Holds the lines to draw later, for underlined style
235  std::vector<float> UnderlineCoords;
236  UnderlineCoords.reserve(16);
237 
238  // Compute the shearing to apply if we're using the italic style
239  float ItalicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
240 
241  // Draw one quad for each character
242  glBegin(GL_QUADS);
243  for (std::size_t i = 0; i < Text.size(); ++i)
244  {
245  // Get the current character and its corresponding glyph
246  Uint32 CurChar = Text[i];
247  const Glyph& CurGlyph = myFont->GetGlyph(CurChar);
248  int Advance = CurGlyph.Advance;
249  const IntRect& Rect = CurGlyph.Rectangle;
250  const FloatRect& Coord = CurGlyph.TexCoords;
251 
252  // If we're using the underlined style and there's a new line,
253  // we keep track of the previous line to draw it later
254  if ((CurChar == L'\n') && (myStyle & Underlined))
255  {
256  UnderlineCoords.push_back(X);
257  UnderlineCoords.push_back(Y + 2);
258  }
259 
260  // Handle special characters
261  switch (CurChar)
262  {
263  case L' ' : X += Advance; continue;
264  case L'\n' : Y += CharSize; X = 0; continue;
265  case L'\t' : X += Advance * 4; continue;
266  case L'\v' : Y += CharSize * 4; continue;
267  }
268 
269  // Draw a textured quad for the current character
270  glTexCoord2f(Coord.Left, Coord.Top); glVertex2f(X + Rect.Left - ItalicCoeff * Rect.Top, Y + Rect.Top);
271  glTexCoord2f(Coord.Left, Coord.Bottom); glVertex2f(X + Rect.Left - ItalicCoeff * Rect.Bottom, Y + Rect.Bottom);
272  glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + Rect.Right - ItalicCoeff * Rect.Bottom, Y + Rect.Bottom);
273  glTexCoord2f(Coord.Right, Coord.Top); glVertex2f(X + Rect.Right - ItalicCoeff * Rect.Top, Y + Rect.Top);
274 
275  // If we're using the bold style, we must render the character 4 more times,
276  // slightly offseted, to simulate a higher weight
277  if (myStyle & Bold)
278  {
279  static const float OffsetsX[] = {-0.5f, 0.5f, 0.f, 0.f};
280  static const float OffsetsY[] = {0.f, 0.f, -0.5f, 0.5f};
281 
282  for (int j = 0; j < 4; ++j)
283  {
284  glTexCoord2f(Coord.Left, Coord.Top); glVertex2f(X + OffsetsX[j] + Rect.Left - ItalicCoeff * Rect.Top, Y + OffsetsY[j] + Rect.Top);
285  glTexCoord2f(Coord.Left, Coord.Bottom); glVertex2f(X + OffsetsX[j] + Rect.Left - ItalicCoeff * Rect.Bottom, Y + OffsetsY[j] + Rect.Bottom);
286  glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + OffsetsX[j] + Rect.Right - ItalicCoeff * Rect.Bottom, Y + OffsetsY[j] + Rect.Bottom);
287  glTexCoord2f(Coord.Right, Coord.Top); glVertex2f(X + OffsetsX[j] + Rect.Right - ItalicCoeff * Rect.Top, Y + OffsetsY[j] + Rect.Top);
288  }
289  }
290 
291  // Advance to the next character
292  X += Advance;
293  }
294  glEnd();
295 
296  // Draw the underlines if needed
297  if (myStyle & Underlined)
298  {
299  // Compute the line thickness
300  float Thickness = (myStyle & Bold) ? 3.f : 2.f;
301 
302  // Add the last line (which was not finished with a \n)
303  UnderlineCoords.push_back(X);
304  UnderlineCoords.push_back(Y + 2);
305 
306  // Draw the underlines as quads
307  GLCheck(glDisable(GL_TEXTURE_2D));
308  glBegin(GL_QUADS);
309  for (std::size_t i = 0; i < UnderlineCoords.size(); i += 2)
310  {
311  glVertex2f(0, UnderlineCoords[i + 1]);
312  glVertex2f(0, UnderlineCoords[i + 1] + Thickness);
313  glVertex2f(UnderlineCoords[i], UnderlineCoords[i + 1] + Thickness);
314  glVertex2f(UnderlineCoords[i], UnderlineCoords[i + 1]);
315  }
316  glEnd();
317  }
318 }
319 
320 
324 void String::RecomputeRect()
325 {
326  // First get the internal UTF-32 string of the text
327  const Unicode::UTF32String& Text = myText;
328 
329  // Reset the "need update" state
330  myNeedRectUpdate = false;
331 
332  // No text, empty box :)
333  if (Text.empty())
334  {
335  myBaseRect = FloatRect(0, 0, 0, 0);
336  return;
337  }
338 
339  // Initial values
340  float CurWidth = 0;
341  float CurHeight = 0;
342  float Width = 0;
343  float Height = 0;
344  float Factor = mySize / myFont->GetCharacterSize();
345 
346  // Go through each character
347  for (std::size_t i = 0; i < Text.size(); ++i)
348  {
349  // Get the current character and its corresponding glyph
350  Uint32 CurChar = Text[i];
351  const Glyph& CurGlyph = myFont->GetGlyph(CurChar);
352  float Advance = CurGlyph.Advance * Factor;
353  const IntRect& Rect = CurGlyph.Rectangle;
354 
355  // Handle special characters
356  switch (CurChar)
357  {
358  case L' ' : CurWidth += Advance; continue;
359  case L'\t' : CurWidth += Advance * 4; continue;
360  case L'\v' : Height += mySize * 4; CurHeight = 0; continue;
361 
362  case L'\n' :
363  Height += mySize;
364  CurHeight = 0;
365  if (CurWidth > Width)
366  Width = CurWidth;
367  CurWidth = 0;
368  continue;
369  }
370 
371  // Advance to the next character
372  CurWidth += Advance;
373 
374  // Update the maximum height
375  float CharHeight = (myFont->GetCharacterSize() + Rect.Bottom) * Factor;
376  if (CharHeight > CurHeight)
377  CurHeight = CharHeight;
378  }
379 
380  // Update the last line
381  if (CurWidth > Width)
382  Width = CurWidth;
383  Height += CurHeight;
384 
385  // Add a slight width / height if we're using the bold style
386  if (myStyle & Bold)
387  {
388  Width += 1 * Factor;
389  Height += 1 * Factor;
390  }
391 
392  // Add a slight width if we're using the italic style
393  if (myStyle & Italic)
394  {
395  Width += 0.208f * mySize;
396  }
397 
398  // Add a slight height if we're using the underlined style
399  if (myStyle & Underlined)
400  {
401  if (CurHeight < mySize + 4 * Factor)
402  Height += 4 * Factor;
403  }
404 
405  // Finally update the rectangle
406  myBaseRect.Left = 0;
407  myBaseRect.Top = 0;
408  myBaseRect.Right = Width;
409  myBaseRect.Bottom = Height;
410 }
411 
412 } // namespace sf
String()
Default constructor.
Definition: String.cpp:39
void SetFont(const Font &CharFont)
Set the font of the string.
Definition: String.cpp:75
T x
X coordinate of the vector.
Definition: Vector2.hpp:59
const Vector2f & GetScale() const
Get the current scale of the object.
Definition: Drawable.cpp:222
void SetStyle(unsigned long TextStyle)
Set the style of the text The default style is Regular.
Definition: String.cpp:102
Characters are underlined.
Definition: String.hpp:56
void SetSize(float Size)
Set the size of the string The default size is 30.
Definition: String.cpp:88
Characters are in italic.
Definition: String.hpp:55
Characters are bold.
Definition: String.hpp:54
FloatRect TexCoords
Texture coordinates of the glyph inside the bitmap font.
Definition: Glyph.hpp:55
T Right
Right coordinate of the rectangle.
Definition: Rect.hpp:114
Font is the low-level class for loading and manipulating character fonts.
Definition: Font.hpp:54
This class is an abstract definition of a unicode text, it can be converted from and to any kind of s...
Definition: Unicode.hpp:63
virtual void Render(RenderTarget &Target) const
/see Drawable::Render
Definition: String.cpp:213
const Font & GetFont() const
Get the font used by the string.
Definition: String.cpp:124
IntRect Rectangle
Bounding rectangle of the glyph, in relative coordinates.
Definition: Glyph.hpp:54
String defines a graphical 2D text, that can be drawn on screen.
Definition: String.hpp:44
int Advance
Offset to move horizontically to the next character.
Definition: Glyph.hpp:53
const Vector2f & GetCenter() const
Get the center of the object.
Definition: Drawable.cpp:231
Structure describing a glyph (a visual character)
Definition: Glyph.hpp:40
unsigned long GetStyle() const
Get the style of the text.
Definition: String.cpp:142
float GetSize() const
Get the size of the characters.
Definition: String.cpp:133
T Bottom
Bottom coordinate of the rectangle.
Definition: Rect.hpp:115
T y
Y coordinate of the vector.
Definition: Vector2.hpp:60
const Vector2f & GetPosition() const
Get the position of the object.
Definition: Drawable.cpp:213
void SetText(const Unicode::Text &Text)
Set the text (from any kind of string)
Definition: String.cpp:65
Base class for all render targets (window, image, ...)
sf::Vector2f GetCharacterPos(std::size_t Index) const
Return the visual position of the Index-th character of the string, in coordinates relative to the st...
Definition: String.cpp:153
T Top
Top coordinate of the rectangle.
Definition: Rect.hpp:113
const Unicode::Text & GetText() const
Get the text (the returned text can be converted implicitely to any kind of string) ...
Definition: String.cpp:115
FloatRect GetRect() const
Get the string rectangle on screen.
Definition: String.cpp:195
T Left
Left coordinate of the rectangle.
Definition: Rect.hpp:112