Different colours in one string
Moderators: CEGUI MVP, CEGUI Team
ldb wrote:Rackle wrote:Let's make every text displayed based on the static text widget.
this seems like way overkill for simply drawing text. it would increase the overhead considerably and add a lot of, what i would guess, un-needed functionality to a simple text string (event handlers, etc).
i just wanted to clarify my complete ignorance on the point i tried to make about "overhead" and "un-needed functionality". i had no idea what i was talking about.
the reason i say this is because i hadnt experimented enough and realized (through forum searches) that calling Font::drawText directly is a bad idea, and that all text drawing, at the very minimum, should be done through CEGUI::Window.
Last edited by ldb on Sun May 06, 2007 14:17, edited 2 times in total.
No matter where you go, there you are.
i have a pretty simple implementation working now.
http://www.puresimplicity.net/~ldb/font ... gger.patch
you can use it like this:
Font::setColourTriggerEnabled(true);
Font::setColourTrigger("^");
Window::setText("^FF0000FFthis is a red string. ^00FF00FFthis is green string.");
http://www.puresimplicity.net/~ldb/font ... gger.patch
you can use it like this:
Font::setColourTriggerEnabled(true);
Font::setColourTrigger("^");
Window::setText("^FF0000FFthis is a red string. ^00FF00FFthis is green string.");
No matter where you go, there you are.
Looks promising.
* you should replace tabs with spaces so your code integrates seamlessly with CEGUI's code.
* I think your code should be more error-proof. With incomplete strings, it should crash or act crazy: (not tested because I can't apply the patch right now.)
- "bla ^FFijkl"
- "bla ^"
I think it's possible to read the whole color code once and then use the argb_t color type witch is an uint_32. Later, changing the ARGB order could be achieved by shifting (I think) and you only need one call to sscanf, that would speed it up. I'll tr my luck when I'm home, this afternoon
thanks for the work done yet
* you should replace tabs with spaces so your code integrates seamlessly with CEGUI's code.
* I think your code should be more error-proof. With incomplete strings, it should crash or act crazy: (not tested because I can't apply the patch right now.)
- "bla ^FFijkl"
- "bla ^"
I think it's possible to read the whole color code once and then use the argb_t color type witch is an uint_32. Later, changing the ARGB order could be achieved by shifting (I think) and you only need one call to sscanf, that would speed it up. I'll tr my luck when I'm home, this afternoon
thanks for the work done yet
Pompei2 wrote:Looks promising.
* you should replace tabs with spaces so your code integrates seamlessly with CEGUI's code.
yup, cant seem to figure out how to make visual studio do that (actually, i just tried "Untabify Selection" and that seems to work, it would be nice if visual studio would just use spaces when i hit the tab key rather than inserting tabs, though)
Pompei2 wrote:* I think your code should be more error-proof. With incomplete strings, it should crash or act crazy: (not tested because I can't apply the patch right now.)
- "bla ^FFijkl"
- "bla ^"
definitly. what do you think about something like this (a check to make sure its not going to read past the end of the string):
Code: Select all
if (changeColor)
{
c += triglen;
if (c + 8 < text.length())
{
memcpy(buf, &str[c], 8);
sscanf(buf, "%x", &argb);
curColour.setColours(argb);
c += 8;
}
}
ive tested it and it works. ive fed it a string like "^" with no ill results.
Pompei2 wrote:I think it's possible to read the whole color code once and then use the argb_t color type witch is an uint_32. Later, changing the ARGB order could be achieved by shifting (I think) and you only need one call to sscanf, that would speed it up. I'll tr my luck when I'm home, this afternoon
yup im playing around and actually got it all down to 1 memcpy and 1 sscanf using the argb_t type like so (which ive tested and works):
Code: Select all
memcpy(buf, &str[c], 8);
sscanf(buf, "%x", &argb);
a = (argb >> 24 & 0xFF) / 255.0;
r = (argb >> 16 & 0xFF) / 255.0;
g = (argb >> 8 & 0xFF) / 255.0;
b = (argb & 0xFF) / 255.0;
curColour.setColours(colour(r, g, b, a));
bla, i actually trimmed it down to this (which assumes your hex color string is in argb format). no sense in switching around the order of the bytes.
Code: Select all
c += triglen;
memcpy(buf, &str[c], 8);
sscanf(buf, "%x", &argb);
curColour.setColours(argb);
c += 8;
i think that ones a winner.
Pompei2 wrote:thanks for the work done yet
bah, its just a hack at the moment, but thanks =)
i updated the patch with the change and changed tabs to spaces:
http://www.puresimplicity.net/~ldb/font ... gger.patch
also, im not all that happy with how i determine whether or not a colour trigger has been detected. it could be better.
Last edited by ldb on Mon May 07, 2007 12:03, edited 2 times in total.
No matter where you go, there you are.
Pompei2 wrote:ldb wrote:also, im not all that happy with how i determine whether or not a colour trigger has been detected. it could be better.
is there a reason why you don't use one of the various CEGUI::String::compare functions ?
none. im open to suggestions.
i suspect that all of this:
Code: Select all
...
bool changeColor;
for (unsigned int i = 0; i < triglen; i++)
{
if (text[c+i] == d_colourFormatTrigger[i])
changeColor = true;
else
changeColor = false;
}
if (changeColor)
...
can be simplified to a single conditional statement.
Last edited by ldb on Mon May 07, 2007 12:41, edited 1 time in total.
No matter where you go, there you are.
another thing i had tried earlier is enable/disable and colour trigger per widget.
my approach was to add a window property which turned it on and off, and had the colour trigger. i got the properties added. but, since this stuff has to be done within the font class, i couldn't figure out how to determine the window that was doing the text rendering (which i need in the font class, in order to determine whether or not to do the colour trigger handling).
so, i figured the next best thing was to allow enable/disable and setting the colour trigger on a per-font basis, which actually isnt all that bad.
also, Font::drawWrappedText(), Font::drawTextLineJustified() probably need modified too. and im pretty sure all the text extent methods need modified.
my approach was to add a window property which turned it on and off, and had the colour trigger. i got the properties added. but, since this stuff has to be done within the font class, i couldn't figure out how to determine the window that was doing the text rendering (which i need in the font class, in order to determine whether or not to do the colour trigger handling).
so, i figured the next best thing was to allow enable/disable and setting the colour trigger on a per-font basis, which actually isnt all that bad.
also, Font::drawWrappedText(), Font::drawTextLineJustified() probably need modified too. and im pretty sure all the text extent methods need modified.
No matter where you go, there you are.
ldb wrote:also, Font::drawWrappedText(), Font::drawTextLineJustified() probably need modified too. and im pretty sure all the text extent methods need modified.
That's where I was going in my post about centralizing every text rendering widget. Maybe my suggestion about using a StaticText widget everywhere wasn't on the mark but the intention was there.
The advantage of only modifying the colors is that it does not affect the text rendering functions. Modifying the bold style makes the text a little bigger which has an effect on the text rendering functions. I doubt that italic and underline have an effect; underline could be implemented just like the color modification.
My goal with an underline style is to support hyperlinks.
Like I wrote earlier, I'm not doing anything with this, just thinking about it.
ldb wrote:i suspect that all of this:Code: Select all
...
bool changeColor;
for (unsigned int i = 0; i < triglen; i++)
{
if (text[c+i] == d_colourFormatTrigger[i])
changeColor = true;
else
changeColor = false;
}
if (changeColor)
...
can be simplified to a single conditional statement.
Yup, But i think your code is the quickest possible.
No, I think the per-window activation IS the best. You could extend the font class to have:
- drawText, that doesn't know about colors, or maybe skips the color codes)
- drawColoredText, that draws the text with the colors.
And then in the window you call one of the two functions, depending on whether the property is activated or not. Then the font functions don't need to know about the window.
You could also achieve this by using function pointers to speed up the thing
Pompei2 wrote:ldb wrote:i suspect that all of this:Code: Select all
...
bool changeColor;
for (unsigned int i = 0; i < triglen; i++)
{
if (text[c+i] == d_colourFormatTrigger[i])
changeColor = true;
else
changeColor = false;
}
if (changeColor)
...
can be simplified to a single conditional statement.
Yup, But i think your code is the quickest possible.
thanks.
No, I think the per-window activation IS the best. You could extend the font class to have:
- drawText, that doesn't know about colors, or maybe skips the color codes)
- drawColoredText, that draws the text with the colors.
And then in the window you call one of the two functions, depending on whether the property is activated or not. Then the font functions don't need to know about the window.
this is actually the exact same idea i had toyed around with trying. except what i was doing is adding an extra parameter to the Font::drawText() method (but that quickly got very ugly).
the reason i thought it got ugly is that i was passing a bool to tell it whether or not to do color parsing, but i also stored the trigger string in the window property, so that wasnt available to me and i couldnt think of an elegant solution for providing that, other than maybe yet another parameter added to the drawText stuff (which i though was spiraling out of control, and once i started thinking of passing a window pointer into drawText(), i knew i had to stop).
No matter where you go, there you are.
ldb wrote:the reason i thought it got ugly is that i was passing a bool to tell it whether or not to do color parsing
you don't need this if you write two distinct font rendering functions, am I right ?
ldb wrote:but i also stored the trigger string in the window property
I thought that there should only be one trigger globally, that is the same overall ? and set with something like CEGUI::FontManager::getSingleton( ).setColorTrigger( "bla" ); then you could get it in the text rendering functions by a call to CEGUI::FontManager::getSingleton( ).getColorTrigger( ); or something similar, no ?
PS: I don't know very good the internals of CEGUI, so it's possible that I propose you impossible things
Pompei2 wrote:ldb wrote:the reason i thought it got ugly is that i was passing a bool to tell it whether or not to do color parsing
you don't need this if you write two distinct font rendering functions, am I right ?
yes, that would eliminate the need for passing extra parameters to the existing text drawing methods. the bad thing is that now there are 2 sets of methods to maintain.
Pompei2 wrote:ldb wrote:but i also stored the trigger string in the window property
I thought that there should only be one trigger globally, that is the same overall ? and set with something like CEGUI::FontManager::getSingleton( ).setColorTrigger( "bla" ); then you could get it in the text rendering functions by a call to CEGUI::FontManager::getSingleton( ).getColorTrigger( ); or something similar, no ?
that would work. but, it is entirely possible people might want different requirements based on the type of window they are using, based on the text data in those windows. not too sure about this. im probably overthinking the whole thing. i think its fair to say the whole font colour thing is going to be limited to a small set of windows, so a global trigger is probably the best way to do it at the moment.
PS: I don't know very good the internals of CEGUI, so it's possible that I propose you impossible things
i am just learning them myself. im still experimenting so i can understand what is possible, and what is not. but, given my current knowledge, nothing you suggest is impossible.
also, everything seems to suggest that Rackles point about centralizing all text rendering widgets is the way to go.
edit:
ive decided im not even going to bother hacking the text extents stuff or the other drawTextLine methods, since i think the time could be spent approaching the design from a different perspective, based on more input from anyone interested.
No matter where you go, there you are.
ldb wrote:Pompei2 wrote:ldb wrote:also, im not all that happy with how i determine whether or not a colour trigger has been detected. it could be better.
is there a reason why you don't use one of the various CEGUI::String::compare functions ?
none. im open to suggestions.
i suspect that all of this:Code: Select all
...
bool changeColor;
for (unsigned int i = 0; i < triglen; i++)
{
if (text[c+i] == d_colourFormatTrigger[i])
changeColor = true;
else
changeColor = false;
}
if (changeColor)
...
can be simplified to a single conditional statement.
i should have said "i suspect all of this doesnt work", because it didnt.
this is what i have now and is a single conditional. i feel pretty stupid for not thinking about using strncmp().
Code: Select all
if (d_colourFormatEnabled)
{
if (c + triglen + 8 <= textlen)
{
if (strncmp(&str[c], trigstr, triglen) == 0)
{
c += triglen;
memcpy(buf, &str[c], 8);
sscanf(buf, "%x", &argb);
curColour.setColours(argb);
c += 8;
}
}
}
dunno if anyone is even following this thread, but if so, i updated my patch file with the change. im pretty sure this one will work as expected unlike the previous one. i also modified getTextExtent() to work with the colour formatting.
http://www.puresimplicity.net/~ldb/font ... gger.patch
No matter where you go, there you are.
Return to “Bug Reports, Suggestions, Feature Requests”
Who is online
Users browsing this forum: No registered users and 3 guests