SFML logo
  • Main Page
  • Namespaces
  • Classes
  • Files
  • File List

Text.cpp

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  ::