SFML community forums

Help => Graphics => Topic started by: zakkor on April 18, 2014, 08:03:34 pm

Title: sf::Text wrap?
Post by: zakkor on April 18, 2014, 08:03:34 pm
After some digging around, I couldn't find much. Any idea how to insert a newline if the text goes off screen? Also: if i display a sf::Text like "testing \n newline" it will just display it on the same line, no newline.
Title: Re: sf::Text wrap?
Post by: Jesper Juhl on April 18, 2014, 08:37:01 pm
There are multiple threads on the forum dealing with this - search for them.

One simple way to do it, if you want to do automatic line wrap, would be to calculate the width of the string word for word until the length is too long, then back up one word and draw that substring. Then move down one line on the screen and continue the process with the remaining string.

If you just want a newline at a specific spot, then just cut the string into two pieces at that point and draw the two strings on two lines.

In any case, SFML won't do it automatically for you. You have to implement your own line wrap algorithm.
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 08:56:34 pm
Do you mean I need to create a new text object and draw it under the previous object for each new line?
Title: Re: sf::Text wrap?
Post by: Jesper Juhl on April 18, 2014, 08:59:05 pm
Do you mean I need to create a new text object and draw it under the previous object for each new line?
That's what I meant. Yes. Or reuse the same sf::Text object but change the text and location for each line.
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 09:06:47 pm
Alrighty. One more thing: How do I figure out exactly how wide any given text is? Also, how do I know how much lower to render the text on the new line, regardless of font size?
Title: Re: sf::Text wrap?
Post by: Nexus on April 18, 2014, 09:13:00 pm
Also: if i display a sf::Text like "testing \n newline" it will just display it on the same line, no newline.
Which SFML version are you using? I'm asking because SFML does handle newlines.

How do I figure out exactly how wide any given text is? Also, how do I know how much lower to render the text on the new line, regardless of font size?
Take a look at the documentation of sf::Text, sf::Font and sf::Glyph. The API provides all the necessary methods to find out these metrics.
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 09:42:39 pm
Which SFML version are you using? I'm asking because SFML does handle newlines.
The latest one I think? 2.1

Is it as simple as just creating a sf::Text object and setting the text to something like "te \n st" ? Because I'm doing that and it doesnt seem to be working.
Title: Re: sf::Text wrap?
Post by: Nexus on April 18, 2014, 09:48:51 pm
Yes. The following works (latest development version from GitHub):
#include <SFML/Graphics.hpp>

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

        sf::Font font;
        font.loadFromFile("sansation.ttf");

        sf::Text text("hello\nworld", font, 40);

        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();
                window.draw(text);
                window.display();
        }
}
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 09:52:28 pm
Shit, you're right. I fiddled around with my stuff and it appears my input thingy is messing with the escape sequence somehow. Anyway, thanks.
Title: Re: sf::Text wrap?
Post by: Jesper Juhl on April 18, 2014, 09:54:36 pm
Seems I have to revisit some of my own code. I couldn't get word wrapping and newlines to work either and implemented it "manually". If \n is supposed to work then I must also have been doing something wrong.
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 10:00:07 pm

text.setString(std::get<0> (tuplePar)); //the string is "hello\nworld", same as below


text.setString("hello\nworld");

First example is trying to to set it as a string from a file, and the string gets read correctly( it displays the right thing) but doesnt seem to work.
second example is setting it manually to the exact same string and it works. What's up?
Title: Re: sf::Text wrap?
Post by: Nexus on April 18, 2014, 10:01:07 pm
Your string probably contains \r\n or \r.
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 10:07:41 pm
Also tested by manually setting the string to \n\r or \r and it still works. I wonder what's happening here
Title: Re: sf::Text wrap?
Post by: Nexus on April 18, 2014, 10:10:46 pm
You should try to debug your file I/O and inspect the actual string you're setting. You are reading an actual newline and not \n in characters, are you? Of course, the latter would correspond to an escaped "\\n", i.e. 2 characters.

Quote
\n\r
Windows uses \r\n, not vice versa.
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 10:19:15 pm
"hello\nworld" is the actual string. I wonder if it's getting stripped of its escape sequence properties or something, getting reduced to just flat text. Is that even possible?
I did something like:
goodString.compare(badString);
And the output is -1, so they can't be the same

Also: It's read as a newline in characters. I tried using \\n but it's the same thing :(
Title: Re: sf::Text wrap?
Post by: Nexus on April 18, 2014, 10:30:56 pm
If you write \n in the text file, it's not the same as \n inside a string literal in your code. The former are two characters backlash and n, whereas the latter is an escape sequence newline.

Of course, reading \\n from the file won't help. What you have to do is replace the two characters from the file with a single newline character.
Title: Re: sf::Text wrap?
Post by: zakkor on April 18, 2014, 11:31:18 pm
I have absolutely no idea how to use sf::Font, sf::Glyph and sf::Text to do this, lol.
As far as I understand it, I should get the width (in pixels, right?) of the string using sf::Glyph, then check to see if it's bigger than the width of the window, and if it is, insert a newline at the nearest space?
This is really confusing, I don't know where to begin :(
Title: Re: sf::Text wrap?
Post by: Nexus on April 18, 2014, 11:55:25 pm
I have absolutely no idea how to use sf::Font, sf::Glyph and sf::Text to do this, lol.
That's why there is a documentation.

Yes, you can sum up the character widths until a certain threshold (in your case at the window border), and the word that exceeds that threshold is moved to the next line. But as Jesper Juhl already mentioned, other people have already had this problem, so it might be worth searching first.
Title: Re: sf::Text wrap?
Post by: Laurent on April 19, 2014, 10:35:10 am
Calculating a character position is trickier than just accumulating the glyphs' widths. For this reason, there's a sf::Text::getCharacterPos function which gives you what you want. Call it for every position (from 0 to text size), and when result.x becomes greater than your limit, insert a \n. And start again after the line break.