Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: sf::Text::GetLocalBounds()  (Read 6847 times)

0 Members and 1 Guest are viewing this topic.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
sf::Text::GetLocalBounds()
« on: March 02, 2012, 09:04:57 pm »
Not sure if this is better suited in feature requests. Actually, the topic doesn't concern a new feature, so I put it here. And since it isn't only connected to the whitespace problem, I think it deserves an own thread.

It would be nice if sf::Text::GetLocalBounds() behaved more intuitively. At the moment, the returned height is different depending on the characters in the text (e.g. 'y' is higher than 'a'). While this seems standing to reason, it makes simple use cases like aligning multiple texts to an edge impossible. Additionally, spaces at the end are not considered in the size calculation.

A proposal to compute the size in local coordinates:
sf::Vector2f GetLocalSize(const sf::Text& text)
{
        const sf::String str = text.GetString() + '\n';

        float maxLineWidth = 0.f;
        float lineWidth = 0.f;
        unsigned int lines = 0;

        for (sf::String::ConstIterator itr = str.Begin(); itr != str.End(); ++itr)
        {
                if (*itr == '\n')
                {
                        ++lines;
                        maxLineWidth = std::max(maxLineWidth, lineWidth);
                        lineWidth = 0.f;
                }
                else
                {
                        lineWidth += text.GetFont().GetGlyph(*itr, text.GetCharacterSize(), text.GetStyle() & sf::Text::Bold).Advance;
                }
        }

        const float lineHeight = static_cast<float>(text.GetFont().GetLineSpacing(text.GetCharacterSize()));
        return sf::Vector2f(maxLineWidth, lines * lineHeight);
}
Some operations might be expensive, however a sf::Text could calculate them upon first call and batch them if necessary. And maybe it is appropriate to expand the bounding rect a little bit on the side and to move it towards the bottom, since it exceeds the text at the top. Or just decrease the height at the top ;)

A simple test application:
void DrawText(sf::RenderWindow& window, const char* str, float x, float y)
{
        sf::Text text(str);
        text.SetPosition(x, y);

        sf::Vector2f size = GetLocalSize(text);

        sf::RectangleShape shape(size);
        shape.SetPosition(text.GetPosition());
        shape.SetFillColor(sf::Color::Transparent);
        shape.SetOutlineColor(sf::Color::Yellow);
        shape.SetOutlineThickness(1.f);

        window.Draw(text);
        window.Draw(shape);
}

int main()
{
        sf::RenderWindow window(sf::VideoMode(640, 480), "SFML Application");
        window.SetFramerateLimit(20);

        while (window.IsOpen())
        {
                sf::Event event;
                while (window.PollEvent(event))
                {
                        if (event.Type == sf::Event::KeyPressed || event.Type == sf::Event::Closed)
                                return 0;
                }

                window.Clear();

                DrawText(window, "hello", 10.f, 10.f);
                DrawText(window, "hello ", 10.f, 60.f);
                DrawText(window, "hello d", 10.f, 110.f);

                DrawText(window, "contains some spaces", 150.f, 10.f);
                DrawText(window, "and a tab\t", 150.f, 60.f);

                DrawText(window, "multiline\ntext", 10.f, 200.f);
                DrawText(window, "text\nmultiline", 150.f, 200.f);

                DrawText(window, "some\nreally long text\neven\nspread across\nmultiple lines.", 350.f, 200.f);

                window.Display();
        }
}
« Last Edit: October 11, 2012, 02:35:53 pm by Laurent »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
sf::Text::GetLocalBounds()
« Reply #1 on: March 02, 2012, 09:14:47 pm »
Thanks, I'll definitely test it and consider your solution.

My todo list is currently full so don't expect feedback from me soon, though.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
sf::Text::GetLocalBounds()
« Reply #2 on: March 02, 2012, 09:21:36 pm »
Thanks for the response!

Yes, it's not a high-priority task, and it can also be fixed without touching the API. So focus on the important tasks for SFML 2.0 ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: