Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify sf::Text::getLocalBounds() to behave more intuitively #216

Closed
Bromeon opened this issue Apr 29, 2012 · 13 comments
Closed

Modify sf::Text::getLocalBounds() to behave more intuitively #216

Bromeon opened this issue Apr 29, 2012 · 13 comments
Assignees
Milestone

Comments

@Bromeon
Copy link
Member

Bromeon commented Apr 29, 2012

With its current semantics, getLocalBounds() is not very useful. For example, it depends on single character heights and ignores leading or trailing whitespaces.

Forum threads:
http://en.sfml-dev.org/forums/index.php?topic=7174
http://en.sfml-dev.org/forums/index.php?topic=6672
http://en.sfml-dev.org/forums/index.php?topic=7156

@ghost ghost assigned LaurentGomila Apr 29, 2012
@eXpl0it3r
Copy link
Member

@LaurentGomila
Copy link
Member

Actually, as long as you take in account the left and top coordinates of the text's bounding rect (which are non-zero, unlike other entities), everything works as expected.

If someone still has a problem, even when left/top coordinates are considered, please post here your use case.

So for now, we're left with just the whitespace issue.

@Wizzard033
Copy link

This could really use being fixed.

@Wizzard033
Copy link

Also, could you expand on what you mean by using the left/top coordinates?

@LaurentGomila
Copy link
Member

Also, could you expand on what you mean by using the left/top coordinates?

I mean doing rect.left + rect.width / 2 to find the center of the bounding rect instead of rect.width / 2, which assumes that rect.left is zero which is generally false for sf::Text.

@LaurentGomila
Copy link
Member

There is still the whitespace issue to fix though.

@Wizzard033
Copy link

I am currently using http://en.sfml-dev.org/forums/index.php?topic=7174 but I don't even think it works properly (although more thorough testing to make sure the bug does not originate elsewhere is necessary). I have to add artificial padding currently to keep text in my GUI text boxes because no proper function exists to measure the text.

@LaurentGomila
Copy link
Member

Please provide a complete and minimal code that reproduces your problem. And as I said, you don't need the workaround shown in that thread if you use the bounding rectangle correctly. So you should also show what you tried with that.

@xparq
Copy link

xparq commented Mar 10, 2023

Hey, happy decennary! ;)
If anyone's actually seeing this (not found an answer in the comments, or elsewhere, actually):

What's the actual use of having an offset bound-rect for sf::Text?

@eXpl0it3r
Copy link
Member

Text should align on the text base and not on whatever the current top left corner is. If you aligned around the top left corner and render the text at position (0, 0), then proceeded to render one letter at a time, you'd get text that jumps around, because let's say you start with a, which is a small letter, but then you expand the text to at suddenly your top left corner is somewhere else relative to the text baseline. Then you add at Z and again there's more vertical space and again some jumping around.

Making sure that text positioning is relative to the text baseline, you can add more and more letters and the text remains stable, while the necessary offset is "absorbed" by the local bounds.

@xparq
Copy link

xparq commented Mar 12, 2023

Thanks for the detailed answer (as usual)! I (kinda) know the reason for the offset, my question is: when this particular way of addressing it -- counter-intuitively special-casing the getLocalBounds API call for just this one case -- is more practical than adding some sf::Text-specific extra methods (like getBaseLineOffset) to address the sf::Text-specific peculiarities.

@eXpl0it3r
Copy link
Member

It's mostly due to the general drawing API design, as getLocalBounds() is part of sf::Transformable.

@xparq
Copy link

xparq commented Mar 21, 2023

I mean exactly because getLocalBounds() is a part of the general drawing API, it's a strange UX surprise to find out that this supposedly uniform API method (for all Transformables) behaves differently for one of them. Especially in light of the API generally being very clean, transparent, straightforward, surprise-free (kudos for all that, @LaurentGomila et al.!).
(In fact, it's a surprise already that it's not just a size vector. Then you'd think maybe because it's relative to the object origin -- but it isn't.)

So, is this more like a historic artifact (and if yes, v3 would be the perfect time to iron it out), or am I (quite possibly!) missing something important here?

In the meantime, I think I've got some better understanding of the assumed motivation:

  • Making getLocalBounds() truly uniform would imply additional calls to Text (to determine positioning offsets not derivable from the size of a piece of text). But the problem is: how exactly to ask Text (or even some other entity?) those questions, and when? With its changing string, Text can't be sure until it makes a measurement, which would be wasteful to do on every get...Offset() call.
  • OTOH, when getLocalBounds() is called, that's a perfect moment to collect those metrics (BTW, I still have no definite idea what the horizontal offset is), and there's those two "unused" coordinates in the rect., begging to hold this data. :) And then all that (those) extra API(s) can just be spared by this neat trick.

But:

  • The SFML API doesn't have the design property of being "minimal" in the sense as to compressing API functionality into as few calls as possible. Its minimalism means cutting back scope instead, while keeping the API very clean and super consistent.

  • Those measurements could be cached in a Text object (refreshed implicitly also by getLocalBounds(), invalidated on setString() etc.).


So, to reverse Laurent's decade-old comment ("If someone still has a problem ... please post here your use case"), and to repeat mine:

What's the use-case that warrants this (apparent) quirk of the otherwise pristine API? (As opposed to providing the same functionality via -- albeit extra, but -- unsurprising, and also more expressive API calls?)

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants