String.cpp
1
2//
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
34namespace sf
35{
40myFont (&Font::GetDefaultFont()),
41mySize (30.f),
42myStyle (Regular),
43myNeedRectUpdate(true)
44{
45
46}
47
48
52String::String(const Unicode::Text& Text, const Font& CharFont, float Size) :
53myFont (&CharFont),
54mySize (Size),
55myStyle (Regular),
56myNeedRectUpdate(true)
57{
58 SetText(Text);
59}
60
61
66{
67 myNeedRectUpdate = true;
68 myText = Text;
69}
70
71
75void String::SetFont(const Font& CharFont)
76{
77 if (myFont != &CharFont)
78 {
79 myNeedRectUpdate = true;
80 myFont = &CharFont;
81 }
82}
83
84
88void String::SetSize(float Size)
89{
90 if (mySize != Size)
91 {
92 myNeedRectUpdate = true;
93 mySize = Size;
94 }
95}
96
97
102void 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
124const Font& String::GetFont() const
125{
126 return *myFont;
127}
128
129
133float String::GetSize() const
134{
135 return mySize;
136}
137
138
142unsigned long String::GetStyle() const
143{
144 return myStyle;
145}
146
147
153sf::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
195FloatRect String::GetRect() const
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
213void String::Render(RenderTarget&) const
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
324void 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
const Vector2f & GetPosition() const
Get the position of the object.
Definition Drawable.cpp:213
const Vector2f & GetScale() const
Get the current scale of the object.
Definition Drawable.cpp:222
const Vector2f & GetCenter() const
Get the center of the object.
Definition Drawable.cpp:231
Font is the low-level class for loading and manipulating character fonts.
Definition Font.hpp:55
Structure describing a glyph (a visual character).
Definition Glyph.hpp:41
IntRect Rectangle
Bounding rectangle of the glyph, in relative coordinates.
Definition Glyph.hpp:54
int Advance
Offset to move horizontically to the next character.
Definition Glyph.hpp:53
FloatRect TexCoords
Texture coordinates of the glyph inside the bitmap font.
Definition Glyph.hpp:55
Rect is an utility class for manipulating rectangles.
Definition Rect.hpp:42
T Top
Top coordinate of the rectangle.
Definition Rect.hpp:113
T Right
Right coordinate of the rectangle.
Definition Rect.hpp:114
T Left
Left coordinate of the rectangle.
Definition Rect.hpp:112
T Bottom
Bottom coordinate of the rectangle.
Definition Rect.hpp:115
const Unicode::Text & GetText() const
Get the text (the returned text can be converted implicitely to any kind of string).
Definition String.cpp:115
const Font & GetFont() const
Get the font used by the string.
Definition String.cpp:124
void SetFont(const Font &CharFont)
Set the font of the string.
Definition String.cpp:75
void SetSize(float Size)
Set the size of the string The default size is 30.
Definition String.cpp:88
FloatRect GetRect() const
Get the string rectangle on screen.
Definition String.cpp:195
void SetStyle(unsigned long TextStyle)
Set the style of the text The default style is Regular.
Definition String.cpp:102
String()
Default constructor.
Definition String.cpp:39
float GetSize() const
Get the size of the characters.
Definition String.cpp:133
void SetText(const Unicode::Text &Text)
Set the text (from any kind of string).
Definition String.cpp:65
virtual void Render(RenderTarget &Target) const
/see Drawable::Render
Definition String.cpp:213
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
unsigned long GetStyle() const
Get the style of the text.
Definition String.cpp:142
@ Regular
Regular characters, no style.
Definition String.hpp:53
@ Bold
Characters are bold.
Definition String.hpp:54
@ Underlined
Characters are underlined.
Definition String.hpp:56
@ Italic
Characters are in italic.
Definition String.hpp:55
This class is an abstract definition of a unicode text, it can be converted from and to any kind of s...
Definition Unicode.hpp:64
T x
X coordinate of the vector.
Definition Vector2.hpp:59
T y
Y coordinate of the vector.
Definition Vector2.hpp:60