- Main Page
- Namespaces
- Classes
- Files

- File List

# String.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/String.hpp>
    00029 #include <SFML/Graphics/Image.hpp>
    00030 #include <SFML/Graphics/GraphicsContext.hpp>
    00031 #include <locale>
    00032
    00033
    00034 namespace sf
    00035 {
    00039 String::String() :
    00040 myFont          (&Font::GetDefaultFont()),
    00041 mySize          (30.f),
    00042 myStyle         (Regular),
    00043 myNeedRectUpdate(true)
    00044 {
    00045
    00046 }
    00047
    00048
    00052 String::String(const Unicode::Text& Text, const Font& CharFont, float Size) :
    00053 myFont          (&CharFont),
    00054 mySize          (Size),
    00055 myStyle         (Regular),
    00056 myNeedRectUpdate(true)
    00057 {
    00058     SetText(Text);
    00059 }
    00060
    00061
    00065 void String::SetText(const Unicode::Text& Text)
    00066 {
    00067     myNeedRectUpdate = true;
    00068     myText = Text;
    00069 }
    00070
    00071
    00075 void String::SetFont(const Font& CharFont)
    00076 {
    00077     if (myFont != &CharFont)
    00078     {
    00079         myNeedRectUpdate = true;
    00080         myFont = &CharFont;
    00081     }
    00082 }
    00083
    00084
    00088 void String::SetSize(float Size)
    00089 {
    00090     if (mySize != Size)
    00091     {
    00092         myNeedRectUpdate = true;
    00093         mySize = Size;
    00094     }
    00095 }
    00096
    00097
    00102 void String::SetStyle(unsigned long TextStyle)
    00103 {
    00104     if (myStyle != TextStyle)
    00105     {
    00106         myNeedRectUpdate = true;
    00107         myStyle = TextStyle;
    00108     }
    00109 }
    00110
    00111
    00115 const Unicode::Text& String::GetText() const
    00116 {
    00117     return myText;
    00118 }
    00119
    00120
    00124 const Font& String::GetFont() const
    00125 {
    00126     return *myFont;
    00127 }
    00128
    00129
    00133 float String::GetSize() const
    00134 {
    00135     return mySize;
    00136 }
    00137
    00138
    00142 unsigned long String::GetStyle() const
    00143 {
    00144     return myStyle;
    00145 }
    00146
    00147
    00153 sf::Vector2f String::GetCharacterPos(std::size_t Index) const
    00154 {
    00155     // First get the UTF32 representation of the text
    00156     const Unicode::UTF32String& Text = myText;
    00157
    00158     // Adjust the index if it's out of range
    00159     if (Index > Text.length())
    00160         Index = Text.length();
    00161
    00162     // The final size is based on the text size
    00163     float FactorX  = mySize / myFont->GetCharacterSize();
    00164     float AdvanceY = mySize;
    00165
    00166     // Compute the position
    00167     sf::Vector2f Position;
    00168     for (std::size_t i = 0; i < Index; ++i)
    00169     {
    00170         // Get the current character and its corresponding glyph
    00171         Uint32       CurChar  = Text[i];
    00172         const Glyph& CurGlyph = myFont->GetGlyph(CurChar);
    00173         float        AdvanceX = CurGlyph.Advance * FactorX;
    00174
    00175         switch (CurChar)
    00176         {
    00177             // Handle special characters
    00178             case L' ' :  Position.x += AdvanceX;                 break;
    00179             case L'\t' : Position.x += AdvanceX * 4;             break;
    00180             case L'\v' : Position.y += AdvanceY * 4;             break;
    00181             case L'\n' : Position.y += AdvanceY; Position.x = 0; break;
    00182
    00183             // Regular character : just add its advance value
    00184             default : Position.x += AdvanceX; break;
    00185         }
    00186     }
    00187
    00188     return Position;
    00189 }
    00190
    00191
    00195 FloatRect String::GetRect() const
    00196 {
    00197     if (myNeedRectUpdate)
    00198         const_cast<String*>(this)->RecomputeRect();
    00199
    00200     FloatRect Rect;
    00201     Rect.Left   = (myBaseRect.Left   - GetCenter().x) * GetScale().x + GetPosition().x;
    00202     Rect.Top    = (myBaseRect.Top    - GetCenter().y) * GetScale().y + GetPosition().y;
    00203     Rect.Right  = (myBaseRect.Right  - GetCenter().x) * GetScale().x + GetPosition().x;
    00204     Rect.Bottom = (myBaseRect.Bottom - GetCenter().y) * GetScale().y + GetPosition().y;
    00205
    00206     return Rect;
    00207 }
    00208
    00209
    00213 void String::Render(RenderTarget&) const
    00214 {
    00215     // First get the internal UTF-32 string of the text
    00216     const Unicode::UTF32String& Text = myText;
    00217
    00218     // No text, no rendering :)
    00219     if (Text.empty())
    00220         return;
    00221
    00222     // Set the scaling factor to get the actual size
    00223     float CharSize =  static_cast<float>(myFont->GetCharacterSize());
    00224     float Factor   = mySize / CharSize;
    00225     GLCheck(glScalef(Factor, Factor, 1.f));
    00226
    00227     // Bind the font texture
    00228     myFont->GetImage().Bind();
    00229
    00230     // Initialize the rendering coordinates
    00231     float X = 0.f;
    00232     float Y = CharSize;
    00233
    00234     // Holds the lines to draw later, for underlined style
    00235     std::vector<float> UnderlineCoords;
    00236     UnderlineCoords.reserve(16);
    00237
    00238     // Compute the shearing to apply if we're using the italic style
    00239     float ItalicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
    00240
    00241     // Draw one quad for each character
    00242     glBegin(GL_QUADS);
    00243     for (std::size_t i = 0; i < Text.size(); ++i)
    00244     {
    00245         // Get the current character and its corresponding glyph
    00246         Uint32           CurChar  = Text[i];
    00247         const Glyph&     CurGlyph = myFont->GetGlyph(CurChar);
    00248         int              Advance  = CurGlyph.Advance;
    00249         const IntRect&   Rect     = CurGlyph.Rectangle;
    00250         const FloatRect& Coord    = CurGlyph.TexCoords;
    00251
    00252         // If we're using the underlined style and there's a new line,
    00253         // we keep track of the previous line to draw it later
    00254         if ((CurChar == L'\n') && (myStyle & Underlined))
    00255         {
    00256             UnderlineCoords.push_back(X);
    00257             UnderlineCoords.push_back(Y + 2);
    00258         }
    00259
    00260         // Handle special characters
    00261         switch (CurChar)
    00262         {
    00263             case L' ' :  X += Advance;         continue;
    00264             case L'\n' : Y += CharSize; X = 0; continue;
    00265             case L'\t' : X += Advance  * 4;    continue;
    00266             case L'\v' : Y += CharSize * 4;    continue;
    00267         }
    00268
    00269         // Draw a textured quad for the current character
    00270         glTexCoord2f(Coord.Left,  Coord.Top);    glVertex2f(X + Rect.Left  - ItalicCoeff * Rect.Top,    Y + Rect.Top);
    00271         glTexCoord2f(Coord.Left,  Coord.Bottom); glVertex2f(X + Rect.Left  - ItalicCoeff * Rect.Bottom, Y + Rect.Bottom);
    00272         glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + Rect.Right - ItalicCoeff * Rect.Bottom, Y + Rect.Bottom);
    00273         glTexCoord2f(Coord.Right, Coord.Top);    glVertex2f(X + Rect.Right - ItalicCoeff * Rect.Top,    Y + Rect.Top);
    00274
    00275         // If we're using the bold style, we must render the character 4 more times,
    00276         // slightly offseted, to simulate a higher weight
    00277         if (myStyle & Bold)
    00278         {
    00279             static const float OffsetsX[] = {-0.5f, 0.5f, 0.f, 0.f};
    00280             static const float OffsetsY[] = {0.f, 0.f, -0.5f, 0.5f};
    00281
    00282             for (int j = 0; j < 4; ++j)
    00283             {
    00284                 glTexCoord2f(Coord.Left,  Coord.Top);    glVertex2f(X + OffsetsX[j] + Rect.Left  - ItalicCoeff * Rect.Top,    Y + OffsetsY[j] + Rect.Top);
    00285                 glTexCoord2f(Coord.Left,  Coord.Bottom); glVertex2f(X + OffsetsX[j] + Rect.Left  - ItalicCoeff * Rect.Bottom, Y + OffsetsY[j] + Rect.Bottom);
    00286                 glTexCoord2f(Coord.Right, Coord.Bottom); glVertex2f(X + OffsetsX[j] + Rect.Right - ItalicCoeff * Rect.Bottom, Y + OffsetsY[j] + Rect.Bottom);
    00287                 glTexCoord2f(Coord.Right, Coord.Top);    glVertex2f(X + OffsetsX[j] + Rect.Right - ItalicCoeff * Rect.Top,    Y + OffsetsY[j] + Rect.Top);
    00288             }
    00289         }
    00290
    00291         // Advance to the next character
    00292         X += Advance;
    00293     }
    00294     glEnd();
    00295
    00296     // Draw the underlines if needed
    00297     if (myStyle & Underlined)
    00298     {
    00299         // Compute the line thickness
    00300         float Thickness = (myStyle & Bold) ? 3.f : 2.f;
    00301
    00302         // Add the last line (which was not finished with a \n)
    00303         UnderlineCoords.push_back(X);
    00304         UnderlineCoords.push_back(Y + 2);
    00305
    00306         // Draw the underlines as quads
    00307         GLCheck(glDisable(GL_TEXTURE_2D));
    00308         glBegin(GL_QUADS);
    00309         for (std::size_t i = 0; i < UnderlineCoords.size(); i += 2)
    00310         {
    00311             glVertex2f(0,                  UnderlineCoords[i + 1]);
    00312             glVertex2f(0,                  UnderlineCoords[i + 1] + Thickness);
    00313             glVertex2f(UnderlineCoords[i], UnderlineCoords[i + 1] + Thickness);
    00314             glVertex2f(UnderlineCoords[i], UnderlineCoords[i + 1]);
    00315         }
    00316         glEnd();
    00317     }
    00318 }
    00319
    00320
    00324 void String::RecomputeRect()
    00325 {
    00326     // First get the internal UTF-32 string of the text
    00327     const Unicode::UTF32String& Text = myText;
    00328
    00329     // Reset the "need update" state
    00330     myNeedRectUpdate = false;
    00331
    00332     // No text, empty box :)
    00333     if (Text.empty())
    00334     {
    00335         myBaseRect = FloatRect(0, 0, 0, 0);
    00336         return;
    00337     }
    00338
    00339     // Initial values
    00340     float CurWidth  = 0;
    00341     float CurHeight = 0;
    00342     float Width     = 0;
    00343     float Height    = 0;
    00344     float Factor    = mySize / myFont->GetCharacterSize();
    00345
    00346     // Go through each character
    00347     for (std::size_t i = 0; i < Text.size(); ++i)
    00348     {
    00349         // Get the current character and its corresponding glyph
    00350         Uint32         CurChar  = Text[i];
    00351         const Glyph&   CurGlyph = myFont->GetGlyph(CurChar);
    00352         float          Advance  = CurGlyph.Advance * Factor;
    00353         const IntRect& Rect     = CurGlyph.Rectangle;
    00354
    00355         // Handle special characters
    00356         switch (CurChar)
    00357         {
    00358             case L' ' :  CurWidth += Advance;                    continue;
    00359             case L'\t' : CurWidth += Advance * 4;                continue;
    00360             case L'\v' : Height   += mySize  * 4; CurHeight = 0; continue;
    00361
    00362             case L'\n' :
    00363                 Height += mySize;
    00364                 CurHeight = 0;
    00365                 if (CurWidth > Width)
    00366                     Width = CurWidth;
    00367                 CurWidth = 0;
    00368                 continue;
    00369         }
    00370
    00371         // Advance to the next character
    00372         CurWidth += Advance;
    00373
    00374         // Update the maximum height
    00375         float CharHeight = (myFont->GetCharacterSize() + Rect.Bottom) * Factor;
    00376         if (CharHeight > CurHeight)
    00377             CurHeight = CharHeight;
    00378     }
    00379
    00380     // Update the last line
    00381     if (CurWidth > Width)
    00382         Width = CurWidth;
    00383     Height += CurHeight;
    00384
    00385     // Add a slight width / height if we're using the bold style
    00386     if (myStyle & Bold)
    00387     {
    00388         Width  += 1 * Factor;
    00389         Height += 1 * Factor;
    00390     }
    00391
    00392     // Add a slight width if we're using the italic style
    00393     if (myStyle & Italic)
    00394     {
    00395         Width += 0.208f * mySize;
    00396     }
    00397
    00398     // Add a slight height if we're using the underlined style
    00399     if (myStyle & Underlined)
    00400     {
    00401         if (CurHeight < mySize + 4 * Factor)
    00402             Height += 4 * Factor;
    00403     }
    00404
    00405     // Finally update the rectangle
    00406     myBaseRect.Left   = 0;
    00407     myBaseRect.Top    = 0;
    00408     myBaseRect.Right  = Width;
    00409     myBaseRect.Bottom = Height;
    00410 }
    00411
    00412 } // namespace sf

:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::