|
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 Agui GUI API -> https://github.com/jmasterx/Agui |
Trezker
Member #1,739
December 2001
|
Very good question IMO. |
LennyLen
Member #5,313
December 2004
|
jmasterx
Member #11,410
October 2009
|
LennyLen said: 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 Agui GUI API -> https://github.com/jmasterx/Agui |
gnolam
Member #2,030
March 2002
|
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. -- |
Dario ff
Member #10,065
August 2008
|
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. 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. |
LennyLen
Member #5,313
December 2004
|
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
|
Text: Text when justified to 30 characters: What the OP wants: This is a short sentence. // ^... the distance from the beginning of the line to here See? -- |
Trezker
Member #1,739
December 2001
|
|
Nazerith
Member #12,551
February 2011
|
It's not particularly pretty, but I filled out your function prototype from above: 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
|
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. -- |
Matthew Leverton
Supreme Loser
January 1999
|
Mark Oates said: 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. 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
|
Matthew Leverton said: You're doing something wrong. My GUI drops way before that. 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. 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: That's a big difference. -- |
Trezker
Member #1,739
December 2001
|
Those texts aren't even justified, they're just word wrapped. |
Mark Oates
Member #1,146
March 2001
|
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. -- |
Matthew Leverton
Supreme Loser
January 1999
|
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
|
Yeah, I feel that's probably the proper approach to this problem. |
|