Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Getting the width of a justified string?

This thread is locked; no one can reply to it. rss feed Print
Getting the width of a justified string?
jmasterx
Member #11,410
October 2009

I would like to add the ability for my textbox to deal with justified. But to do this I would need the width of a string of text when it is justified in order to get the correct caret positioning. Does Allegro 5 provide functions for this? I know I can draw a justified string but I do not know how to get its width.

Thanks

Trezker
Member #1,739
December 2001
avatar

Very good question IMO.
I think this feature might be of interest to me some time in the future since I'm a GUI developer.

LennyLen
Member #5,313
December 2004
avatar

jmasterx
Member #11,410
October 2009

I'm aware of these functions and use them a lot. However I do not see how they can apply to the width of part of a line which has had an arbitrary number of spaces added to it.

What I meant is something maybe like:

al_get_justfied_text_width(const char* textLine, ALLEGRO_FONT *f, int w, int subStrLen);

Which would return the width that that substring of characters would occupy if that line were justified.

This would allow me to accurately figure out where to position my caret

gnolam
Member #2,030
March 2002
avatar

A string should should have exactly the same width regardless of justification. The only difference is the offset, i.e. if it's drawn at x, x - width/2 or x - width.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Dario ff
Member #10,065
August 2008
avatar

gnolam said:

A string should should have exactly the same width regardless of justification. The only difference is the offset, i.e. if it's drawn at x, x - width/2 or x - width.

I know correcting gnolam is dangerous, but that sounds more like alignment rather than justfication. :P

All I can think for getting the width of a justified string, is separating the words and getting the width of each of 'em. If the necessary offset between them to cover the whole width is bigger than the offset you set in al_draw_justified_text, you get the normal text width. If it's smaller, then it's as big as x2-x in the first method. At least that's how I think it should work, I haven't worked with those functions too much.

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

LennyLen
Member #5,313
December 2004
avatar

If the string is being fully justified to fit into an area, then it's width should be the width of the area.

edit: I'd set it to whichever is larger out of the width you're justifying to, or the result of al_get_text_width()

edit 2:

Dario ff said:

I know correcting gnolam is dangerous, but that sounds more like alignment rather than justfication

The terms left- and right-justified used to be used extensively to describe what is generally called left- and right-aligned these days. I made the same assumption that gnolam did.

X-G
Member #856
December 2000
avatar

Text:
This is a short sentence.

Text when justified to 30 characters:
This is a short sentence.

What the OP wants:

This  is  a  short   sentence.
//           ^... the distance from the beginning of the line to here

See?

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Trezker
Member #1,739
December 2001
avatar

What I thought this was about was getting the position of a character somewhere in the middle of a justified string.
Beaten by X-G.

Nazerith
Member #12,551
February 2011

It's not particularly pretty, but I filled out your function prototype from above:

#SelectExpand
1int al_get_justfied_text_width(const char* textLine, ALLEGRO_FONT *f, int w, int subStrLen) 2{ 3 string fullStr, subStr; 4 int strLength, subLength; 5 int fullSpaces, subSpaces; 6 int justifiedPos; 7 8 fullStr = textLine; 9 subStr = fullStr.substr(0,subStrLen); 10 11 fullSpaces = count(fullStr.begin(), fullStr.end(), ' '); 12 subSpaces = count(subStr.begin(), subStr.end(), ' '); 13 14 strLength = al_get_text_width(f, fullStr.c_str()); 15 subLength = al_get_text_width(f, subStr.c_str()); 16 17 justifiedPos = subLength + (((w-strLength) / fullSpaces) * subSpaces); 18 19 return (justifiedPos); 20}

That will give you the position of something like a cursor at a certain position. It assumes all spaces are set to equal width in order to justify the string to the width passed as 'w'.

Is that what you were looking for? I'm not sure if I totally misunderstood the question here.

Mark Oates
Member #1,146
March 2001
avatar

Getting the width of a text render can be an expensive operation, enough that if you fit it in to a box of, say, 500 pixels and it has more than 30 lines, you may see a drop in framerates.

You can curb that by creating a cache representing each line and its text width. Then you would only have to take a speed hit when you need to update the data.

The most flexible method I've come up with so far is to spit the text into words, and have a structure that contains the word and it's width. That way you can freely change the width of your box without a speed cost. Also, changing a single word would only require a change to a word-width pair of a single element. You would need to create your own justify function with this method, but it's not difficult.

However, this method has a few holes, but none that I've had to actually deal with in real applications.

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Matthew Leverton
Supreme Loser
January 1999
avatar

Getting the width of a text render can be an expensive operation, enough that if you fit it in to a box of, say, 500 pixels and it has more than 30 lines, you may see a drop in framerates.

You're doing something wrong. My GUI drops way before that. 8-)

jmasterx said:

Does Allegro 5 provide functions for this?

No. Its text drawing is quite limited, unfortunately. You're probably better off creating your own text justifying routine and keep track of lengths of individual words.

Are you really creating a text box that is justified while typing? That sounds like a weird experience. But I could understand the need for selecting or highlighting justified text.

Mark Oates
Member #1,146
March 2001
avatar

You're doing something wrong. My GUI drops way before that. 8-)

:P

Let's see... I did some tests a while back.

Here's an example where the spacing is calculated on each render. The text box is 500px wide, it ends up having about 14 lines.
{"name":"603446","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/0\/802b3d4e31829a226f2a7b35f4f46211.png","w":1075,"h":834,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/0\/802b3d4e31829a226f2a7b35f4f46211"}603446
It looks like the whole operation (User Render) takes about a frame and a half. So you'll get a frame hit at about 10 lines (!!!). :-X

This example already has a pre-calculated word-width set, and words are spaced and rendered each frame. same 500px width, and ends up with about 24 lines:
{"name":"603447","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/2\/32f53e0a2d3e2f06a1e2d71f8b69bf5e.png","w":1075,"h":834,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/2\/32f53e0a2d3e2f06a1e2d71f8b69bf5e"}603447
This one takes only about 1/8 of a frame.

That's a big difference. :-/

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Trezker
Member #1,739
December 2001
avatar

Those texts aren't even justified, they're just word wrapped.

Mark Oates
Member #1,146
March 2001
avatar

Trezker said:

Those texts aren't even justified, they're just word wrapped.

Justification is just a basic calculation on top of that. This is an example of how expensive al_get_text_width() is - an important thing to consider if you're finding points in any text.

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Matthew Leverton
Supreme Loser
January 1999
avatar

Justifying the text would be simple. Just insert extra_space / (word_count - 1) pixels of spacing in between each word.

I haven't written a multiline text widget or display widget yet, but I would basically take a double linked list of pointers to lines. Each line would contain a double linked list of words. Each word would contain its width and spacing information.

From that you'd be able to determine which word the mouse was over. When clicking, you could easily compute the exact character.

Trezker
Member #1,739
December 2001
avatar

Yeah, I feel that's probably the proper approach to this problem.

Go to: