21

I'm using SFML 2.0 libraries on Ubuntu 12.10, using

sudo apt-get install libsfml-dev

to get them. Now I'm trying to get a sf::Text centered in the sreen. To do this, I set the origin of the text (the place that is used to make transformations such as setting position, rotating, etc) to the center of the bounding box of the sf::Text, and then set the position to the center of the screen, like so:

//declare text
sf::Font font;
sf::Text text;
font.loadFromFile("helvetica.ttf");
text.setFont(font);
text.setString("RANDOMTEXT");
text.setCharacterSize(100);
text.setColor(sf::Color::White);
text.setStyle(sf::Text::Regular);

//center text
sf::FloatRect textRect = text.getLocalBounds();
text.setOrigin(textRect.width/2,textRect.height/2);
text.setPosition(sf::Vector2f(SCRWIDTH/2.0f,SCRHEIGHT/2.0f));

This does not work, the text is off by some amount, like 3 on the x axis and 25 on the y axis. Oddly, if you set up a sf::RectangleShape to represent the bounding box of the text, that rectangle IS centered and correctly sized to fit the text. But then the text is drawn out of that box with the previously mentioned offset.

In this image I've marked the center of the screen, painted a sf::RectangleShape in the place of the bounding box of the text, and the sf::Text.

https://i.stack.imgur.com/LvDJc.png

That image was generated by this code:

const int SCRWIDTH = 800; 
const int SCRHEIGHT = 600;

int main() {
sf::RenderWindow window;
window.create(sf::VideoMode(SCRWIDTH,SCRHEIGHT), "MYGAME" ,sf::Style::Default);
window.setMouseCursorVisible(false);
window.setVerticalSyncEnabled(true);

sf::Font font;
sf::Text text;
font.loadFromFile("helvetica.ttf");
text.setFont(font);
text.setString("RANDOMTEXT");
text.setCharacterSize(100);
text.setColor(sf::Color::White);
text.setStyle(sf::Text::Regular);

sf::FloatRect textRect = text.getLocalBounds();

text.setOrigin(textRect.width/2,textRect.height/2);
text.setPosition(sf::Vector2f(SCRWIDTH/2.0f,SCRHEIGHT/2.0f));

sf::RectangleShape rect(sf::Vector2f(textRect.width,textRect.height));
rect.setFillColor(sf::Color::Blue);
rect.setOrigin(rect.getSize().x/2,rect.getSize().y/2);
rect.setPosition(text.getPosition());

sf::RectangleShape RectW;
RectW.setSize(sf::Vector2f(SCRWIDTH, 0.0));
RectW.setOutlineColor(sf::Color::Red);
RectW.setOutlineThickness(1);
RectW.setPosition(0, SCRHEIGHT / 2);
sf::RectangleShape RectH;
RectH.setSize(sf::Vector2f(0.0, SCRHEIGHT));
RectH.setOutlineColor(sf::Color::Red);
RectH.setOutlineThickness(1);
RectH.setPosition(SCRWIDTH / 2, 0);

while(window.isOpen()) {
    window.clear();
    window.draw(rect);
    window.draw(text);
    window.draw(RectW);
    window.draw(RectH);
    window.display();
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
        window.close();
    }
}
return 1;
}

How can I get it to be centered and inside of it's bounding box, as it should be?

Dani Torramilans
  • 340
  • 1
  • 2
  • 7

3 Answers3

40

sf::Text::getLocalBounds() has non-zero values for the top and left fields, so you can't ignore them when centering the origin.

Try this instead:

//center text
sf::FloatRect textRect = text.getLocalBounds();
text.setOrigin(textRect.left + textRect.width/2.0f,
               textRect.top  + textRect.height/2.0f);
text.setPosition(sf::Vector2f(SCRWIDTH/2.0f,SCRHEIGHT/2.0f));
Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
6

I think this is a know problem with SFML's text rendering. Head on over to their issue tracker and take a look at this issue.

Also you could ask at their development forum. The developers their are always very friendly and helpful.

Foaly
  • 565
  • 1
  • 7
  • 22
2

In addition to Emile's answer, instead of using textRect.height, you should use the maxHeight from the code below:

for (size_t characterIndex = 0; characterIndex < text.size(); ++characterIndex)
{
  currentHeight = font->getGlyph(text[characterIndex], 12, false).bounds.height;
  if (currentHeight > maxHeight)
  {
    maxHeight = currentHeight;
  }
}

Explanation here:

This is because the first line is aligned vertically on the height of the tallest character -- even if it's not in your string. This is to keep the top of the string steady even if you add higher characters on the first line.

The exact computation is not straight-forward: you would have to iterate through all the characters of the first line, compute the highest character size, subtract this from the CharacterSize of your sf::Text, and subtract the result from the height of the bounding rectangle.


Another very important note: You may upset the look of the text if you draw it at a non-integer position. This seems to include the origin as well... (So round your origin + position to the nearest integer!)

Andrew
  • 5,839
  • 1
  • 51
  • 72
  • 1
    Nice that you also mention the float->int issue. It's good to know that _it affects everything else_, too, not just text. (Most visibly, perhaps with small detailed parts with pixel-perfect texture mapping, especially when rotated... -- they could end up incredibly wrong just due to the missing/uncontrolled rounding.) – Sz. Mar 10 '23 at 20:51