00001 00002 // 00003 // SFML - Simple and Fast Multimedia Library 00004 // Copyright (C) 2007-2009 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/Text.hpp> 00029 #include <SFML/Graphics/Image.hpp> 00030 #include <SFML/Graphics/Renderer.hpp> 00031 00032 00033 namespace sf 00034 { 00038 Text::Text() : 00039 myFont (&Font::GetDefaultFont()), 00040 myCharacterSize(30), 00041 myStyle (Regular), 00042 myRectUpdated (true) 00043 { 00044 00045 } 00046 00047 00051 Text::Text(const String& string, const Font& font, unsigned int characterSize) : 00052 myFont (&font), 00053 myCharacterSize(characterSize), 00054 myStyle (Regular), 00055 myRectUpdated (true) 00056 { 00057 SetString(string); 00058 } 00059 00060 00064 void Text::SetString(const String& string) 00065 { 00066 myString = string; 00067 myRectUpdated = false; 00068 } 00069 00070 00074 void Text::SetFont(const Font& font) 00075 { 00076 if (myFont != &font) 00077 { 00078 myFont = &font; 00079 myRectUpdated = false; 00080 } 00081 } 00082 00083 00087 void Text::SetCharacterSize(unsigned int size) 00088 { 00089 if (myCharacterSize != size) 00090 { 00091 myCharacterSize = size; 00092 myRectUpdated = false; 00093 } 00094 } 00095 00096 00101 void Text::SetStyle(unsigned long style) 00102 { 00103 if (myStyle != style) 00104 { 00105 myStyle = style; 00106 myRectUpdated = false; 00107 } 00108 } 00109 00110 00114 const String& Text::GetString() const 00115 { 00116 return myString; 00117 } 00118 00119 00123 const Font& Text::GetFont() const 00124 { 00125 return *myFont; 00126 } 00127 00128 00132 unsigned int Text::GetCharacterSize() const 00133 { 00134 return myCharacterSize; 00135 } 00136 00137 00141 unsigned long Text::GetStyle() const 00142 { 00143 return myStyle; 00144 } 00145 00146 00152 Vector2f Text::GetCharacterPos(std::size_t index) const 00153 { 00154 // Make sure that we have a valid font 00155 if (!myFont) 00156 return Vector2f(0, 0); 00157 00158 // Adjust the index if it's out of range 00159 if (index > myString.GetSize()) 00160 index = myString.GetSize(); 00161 00162 // We'll need this a lot 00163 bool bold = (myStyle & Bold) != 0; 00164 float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); 00165 00166 // Compute the position 00167 Vector2f position; 00168 Uint32 prevChar = 0; 00169 float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize)); 00170 for (std::size_t i = 0; i < index; ++i) 00171 { 00172 Uint32 curChar = myString[i]; 00173 00174 // Apply the kerning offset 00175 position.x += static_cast<float>(myFont->GetKerning(prevChar, curChar, myCharacterSize)); 00176 prevChar = curChar; 00177 00178 // Handle special characters 00179 switch (curChar) 00180 { 00181 case L' ' : position.x += space; continue; 00182 case L'\t' : position.x += space * 4; continue; 00183 case L'\v' : position.y += lineSpacing * 4; continue; 00184 case L'\n' : position.y += lineSpacing; position.x = 0; continue; 00185 } 00186 00187 // For regular characters, add the advance offset of the glyph 00188 position.x += static_cast<float>(myFont->GetGlyph(curChar, myCharacterSize, bold).Advance); 00189 } 00190 00191 return position; 00192 } 00193 00194 00198 FloatRect Text::GetRect() const 00199 { 00200 UpdateRect(); 00201 00202 FloatRect rect; 00203 rect.Left = (myBaseRect.Left - GetOrigin().x) * GetScale().x + GetPosition().x; 00204 rect.Top = (myBaseRect.Top - GetOrigin().y) * GetScale().y + GetPosition().y; 00205 rect.Right = (myBaseRect.Right - GetOrigin().x) * GetScale().x + GetPosition().x; 00206 rect.Bottom = (myBaseRect.Bottom - GetOrigin().y) * GetScale().y + GetPosition().y; 00207 00208 return rect; 00209 } 00210 00211 00215 void Text::Render(RenderTarget&, Renderer& renderer) const 00216 { 00217 // No text or not font: nothing to render 00218 if (!myFont || myString.IsEmpty()) 00219 return; 00220 00221 // Bind the font texture 00222 renderer.SetTexture(&myFont->GetImage(myCharacterSize)); 00223 00224 // Computes values related to the text style 00225 bool bold = (myStyle & Bold) != 0; 00226 bool underlined = (myStyle & Underlined) != 0; 00227 float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees 00228 float underlineOffset = myCharacterSize * 0.1f; 00229 float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f); 00230 FloatRect underlineCoords = myFont->GetImage(myCharacterSize).GetTexCoords(IntRect(1, 1, 1, 1)); 00231 00232 // Initialize the rendering coordinates 00233 float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); 00234 float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize)); 00235 float x = 0.f; 00236 float y = static_cast<float>(myCharacterSize); 00237 00238 // Note: 00239 // Here we use a Begin/End pair for each quad because 00240 // the font's texture may change in a call to GetGlyph 00241 00242 // Draw one quad for each character 00243 Uint32 prevChar = 0; 00244 for (std::size_t i = 0; i < myString.GetSize(); ++i) 00245 { 00246 Uint32 curChar = myString[i]; 00247 00248 // Apply the kerning offset 00249 x += static_cast<float>(myFont->GetKerning(prevChar, curChar, myCharacterSize)); 00250 prevChar = curChar; 00251 00252 // If we're using the underlined style and there's a new line, draw a line 00253 if (underlined && (curChar == L'\n')) 00254 { 00255 float top = y + underlineOffset; 00256 float bottom = top + underlineThickness; 00257 00258 renderer.Begin(Renderer::QuadList); 00259 renderer.AddVertex(0, top, underlineCoords.Left, underlineCoords.Top); 00260 renderer.AddVertex(x, top, underlineCoords.Right, underlineCoords.Top); 00261 renderer.AddVertex(x, bottom, underlineCoords.Right, underlineCoords.Bottom); 00262 renderer.AddVertex(0, bottom, underlineCoords.Left, underlineCoords.Bottom); 00263 renderer.End(); 00264 } 00265 00266 // Handle special characters 00267 switch (curChar) 00268 { 00269 case L' ' : x += space; continue; 00270 case L'\t' : x += space * 4; continue; 00271 case L'\n' : y += lineSpacing; x = 0; continue; 00272 case L'\v' : y += lineSpacing * 4; continue; 00273 } 00274 00275 // Extract the current glyph's description 00276 const Glyph& curGlyph = myFont->GetGlyph(curChar, myCharacterSize, bold); 00277 int advance = curGlyph.Advance; 00278 const IntRect& rect = curGlyph.Rectangle; 00279 const FloatRect& coord = curGlyph.TexCoords; 00280 00281 // Draw a textured quad for the current character 00282 renderer.Begin(Renderer::QuadList); 00283 renderer.AddVertex(x + rect.Left - italicCoeff * rect.Top, y + rect.Top, coord.Left, coord.Top); 00284 renderer.AddVertex(x + rect.Right - italicCoeff * rect.Top, y + rect.Top, coord.Right, coord.Top); 00285 renderer.AddVertex(x + rect.Right - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Right, coord.Bottom); 00286 renderer.AddVertex(x + rect.Left - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Left, coord.Bottom); 00287 renderer.End(); 00288 00289 // Advance to the next character 00290 x += advance; 00291 } 00292 00293 // If we're using the underlined style, add the last line 00294 if (underlined) 00295 { 00296 float top = y + underlineOffset; 00297 float bottom = top + underlineThickness; 00298 00299 renderer.Begin(Renderer::QuadList); 00300 renderer.AddVertex(0, top, underlineCoords.Left, underlineCoords.Top); 00301 renderer.AddVertex(x, top, underlineCoords.Right, underlineCoords.Top); 00302 renderer.AddVertex(x, bottom, underlineCoords.Right, underlineCoords.Bottom); 00303 renderer.AddVertex(0, bottom, underlineCoords.Left, underlineCoords.Bottom); 00304 renderer.End(); 00305 } 00306 } 00307 00308 00312 void Text::UpdateRect() const 00313 { 00314 if (myRectUpdated) 00315 return; 00316 00317 // Reset the previous states 00318 myRectUpdated = true; 00319 myBaseRect = FloatRect(0, 0, 0, 0); 00320 00321 // No text or not font: empty box 00322 if (!myFont || myString.IsEmpty()) 00323 return; 00324 00325 // Initial values 00326 bool bold = (myStyle & Bold) != 0; 00327 float charSize = static_cast<float>(myCharacterSize); 00328 float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); 00329 float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize)); 00330 float curWidth = 0; 00331 float curHeight = 0; 00332 float width = 0; 00333 float height = 0; 00334 Uint32 prevChar = 0; 00335 00336 // Go through each character 00337 for (std::size_t i = 0; i < myString.GetSize(); ++i) 00338 { 00339 Uint32 curChar = myString[i]; 00340 00341 // Apply the kerning offset 00342 curWidth += static_cast<float>(myFont->GetKerning(prevChar, curChar, myCharacterSize)); 00343 prevChar = curChar; 00344 00345 // Handle special characters 00346 switch (curChar) 00347 { 00348 case L' ' : 00349 curWidth += space; 00350 continue; 00351 00352 case L'\t' : 00353 curWidth += space * 4; 00354 continue; 00355 00356 case L'\v' : 00357 height += lineSpacing * 4; 00358 curHeight = 0; 00359 continue; 00360 00361 case L'\n' : 00362 height += lineSpacing; 00363 curHeight = 0; 00364 if (curWidth > width) 00365 width = curWidth; 00366 curWidth = 0; 00367 continue; 00368 } 00369 00370 // Extract the current glyph's description 00371 const Glyph& curGlyph = myFont->GetGlyph(curChar, myCharacterSize, bold); 00372 00373 // Advance to the next character 00374 curWidth += static_cast<float>(curGlyph.Advance); 00375 00376 // Update the maximum height 00377 float charHeight = charSize + curGlyph.Rectangle.Bottom; 00378 if (charHeight > curHeight) 00379 curHeight = charHeight; 00380 } 00381 00382 // Update the last line 00383 if (curWidth > width) 00384 width = curWidth; 00385 height += curHeight; 00386 00387 // Add a slight width if we're using the italic style 00388 if (myStyle & Italic) 00389 { 00390 width += 0.208f * charSize; 00391 } 00392 00393 // Add a slight height if we're using the underlined style 00394 if (myStyle & Underlined) 00395 { 00396 float underlineOffset = myCharacterSize * 0.1f; 00397 float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f); 00398 00399 if (curHeight < charSize + underlineOffset + underlineThickness) 00400 height += underlineOffset + underlineThickness; 00401 } 00402 00403 // Finally update the rectangle 00404 myBaseRect.Left = 0; 00405 myBaseRect.Top = 0; 00406 myBaseRect.Right = width; 00407 myBaseRect.Bottom = height; 00408 } 00409 00410 } // namespace sf
:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::