Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [al5]Drawing text line by line rather than char by char?

This thread is locked; no one can reply to it. rss feed Print
 1   2 
[al5]Drawing text line by line rather than char by char?
jmasterx
Member #11,410
October 2009

Would there be a very noticeable performance dent if I drew text char by char rather than line by line?

Say I have:

ABCDEF ABCDEF ABCDEF ABCDEF
GHIJK GHIJK GHIJK GHIJK GHIJK
ABCDEF ABCDEF ABCDEF ABCDEF
GHIJK GHIJK GHIJK GHIJK GHIJK
ABCDEF ABCDEF ABCDEF ABCDEF
GHIJK GHIJK GHIJK GHIJK GHIJK

(or about a good TextBox worth of text)

Would it be much slower to do:

for each char
draw char with its color
increase X by width of char

rather than

for each line of text
draw the text

The reason why is because I'm thinking of doing the former for my Gui's TextBoxes. I want to have gradient text so each char has a different color.

When I tested it didn't seem to be much different, but I want a second opinion.

Thanks

Mark Oates
Member #1,146
March 2001
avatar

jmasterx said:

Would there be a very noticeable performance dent if I drew text char by char rather than line by line?

Not so much. Either way, you'll have a pretty strong hit drawing that much text regardless. Text rendering can be kindof expensive if you do a lot. If it's savings you're after, you'll get a bigger help by rendering your text to a separate bitmap and drawing the bitmap from that point on.

If you want to really measure the difference, you can:

double start = al_get_time();
// do your rendering here
double end = al_get_time();
double time_of_process = end - start;

In my experience, drawing char by char isn't that much more expensive. It's negligible.

Matthew Leverton
Supreme Loser
January 1999
avatar

Thomas Fjellstrom
Member #476
June 2000
avatar

You'll probably get better looking text if you render line by line though. If you go char by char, you'll be missing out on some of the fancier hinting available with TTF fonts. This is assuming you're using TTFs, and not bitmap fonts. If you're using bitmap fonts, you can probably do as you like.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Mark Oates
Member #1,146
March 2001
avatar

You'll probably get better looking text if you render line by line though. If you go char by char, you'll be missing out on some of the fancier hinting available with TTF fonts.

I don't think this is true. Here I've tested 4 TTF fonts, the top (white) is rendered char-by-char and the bottom (pink) is drawn by the line. The hinting appears to be identical on both.

{"name":"603099","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/1\/a1fdbad69e02d26bcebf522cb3fb0987.png","w":801,"h":173,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/1\/a1fdbad69e02d26bcebf522cb3fb0987"}603099
{"name":"603100","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/9\/a953a80079d7cc0f9cb44a97513c1e8f.png","w":645,"h":173,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/9\/a953a80079d7cc0f9cb44a97513c1e8f"}603100
{"name":"603101","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/1\/211f87cc82371bb1e85733e94fb835d2.png","w":645,"h":173,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/1\/211f87cc82371bb1e85733e94fb835d2"}603101
{"name":"603102","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/ac424d7f6ffaa9d56065117586d35e30.png","w":901,"h":173,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/ac424d7f6ffaa9d56065117586d35e30"}603102

Thomas Fjellstrom
Member #476
June 2000
avatar

I could be wrong. But I could swear I've seen fonts that don't display properly if you draw char by char since allegro doesn't let you access all of the hinting info... At most you get access to the "advance" which may be enough for many simple fonts? I dunno.

What I heard is the actual advance between any two characters can be different depending on which character pair is used. So an "a"s advance might not be the same depending on what character follows it. Simple examples like the above might not show any difference...

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

SiegeLord
Member #7,827
October 2006
avatar

Speedwise, it should be nearly the same as long as you hold drawing. As for hinting, you can probably compute it manually by computing widths of pairs of characters.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Mark Oates
Member #1,146
March 2001
avatar

You may be thinking of kerning and or kerning pairs. I found that allegro neglects the kerning pairs between characters. Take for example the font Trajan. The top (white) is drawn by character, the second (pink) is drawn by line, and the third (green) I added with photoshop and includes the appropriate pairs (AV, AW, WA, etc).

{"name":"603103","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/6\/a6ccaca2717c7cc929bd871f8eb5cf8d.png","w":591,"h":173,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/6\/a6ccaca2717c7cc929bd871f8eb5cf8d"}603103

here is 3x zoom with hilights:
{"name":"603105","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/5\/d5412f1bd98694d822eb61590f88a9ca.png","w":335,"h":313,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/5\/d5412f1bd98694d822eb61590f88a9ca"}603105

SiegeLord
Member #7,827
October 2006
avatar

Hmm... unless you load it with ALLEGRO_TTF_NO_KERNING it should work in Allegro too... sounds like a bug.

EDIT:

Well, it works fine with the font used in ex_ttf... so it's a font specific bug.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Mark Oates
Member #1,146
March 2001
avatar

SiegeLord said:

Well, it works fine with the font used in ex_ttf... so it's a font specific bug.

Interesting... I'm finding that some OpenType .otf fonts are not rendering with pairs. I now see that I am getting pairs for my TTF fonts.

here is Constantina (TTF)
{"name":"603107","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/5\/75293a732e954414a74d4e1470bfe64c.png","w":591,"h":173,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/5\/75293a732e954414a74d4e1470bfe64c"}603107

doing more testing...

[edit]

{"name":"603109","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/d\/ed61b7cff515468aa9b8f70b81873732.png","w":670,"h":888,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/d\/ed61b7cff515468aa9b8f70b81873732"}603109
the ones with the arrows are the fonts that do have kerning data but don't render correctly. Each of these are Adobe Fonts (the best ones :() that came with Photoshop and are otf. They're fonts that are part of font sets (bold, italic, regular, bold-italic) and so the kerning may be in the set data, or something fancy like separate glyphs.

dangit. :-/

jmasterx
Member #11,410
October 2009

How can one then get colored text while still maintaining kerning?

Mark Oates
Member #1,146
March 2001
avatar

jmasterx are you using a5? The 5.0 RC versions have color in the function call.

al_draw_text();

jmasterx
Member #11,410
October 2009

Sorry, what I meant is, each letter having a different color. al_draw_text would almost need a callback to change the color.

Matthew Leverton
Supreme Loser
January 1999
avatar

I was going to suggest this:

  1. Draw gradient with alpha = 0%.

  2. Draw font with rgb of 0,0,0 and alpha = 100% using ADD/ONE/ONE for the blender mode.

But I couldn't get it to work.

Mark Oates
Member #1,146
March 2001
avatar

But I couldn't get it to work.

I think something was borked in RC4 with the blenders (fixed in SVN?). My 0.0f alpha images are all drawn as if they were additive blending with 1.0 transparency.

jmasterx
Member #11,410
October 2009

Hmmm that won't be flexible enough, I'm gonna be making colored textboxes for my gui api and I'll need to be able to color a selection.

Matthew Leverton
Supreme Loser
January 1999
avatar

I think something was borked in RC4 with the blenders

That looks like a D3D thing (judging by Peter's comments), but I'm on Linux (opengl).

Arthur Kalliokoski
Second in Command
February 2005
avatar

But I could swear I've seen fonts that don't display properly if you draw char by char since allegro doesn't let you access all of the hinting info...

IIRC, there's two kinds of "hinting", one has narrow widths for narrow chars and vice versa, and the other patented kind takes the next char into account, such as "TF" vs. "Tf" (the serif on the f fits under the crossbar on the T).

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Elias
Member #358
May 2000

I think hinting is patented and therefore not included in Freetype. Kerning however should work - I don't know why it seems to be missing for some fonts. Most likely a bug in the TTF addon.

To render char-by-char, the best way would probably be a special function for it. Right now if you render e.g. the text "AV", then al_get_text_width("AV") will be smaller than al_get_text_width("A") + al_get_text_width("V") because of the kerning - the only way to get the exact position of the "V" would be if you could get the kerning offset of the "AV" pair. Maybe a function like

float al_get_char_pos(float x, char const *text, char const *letter);

Then if you call it as al_get_char_pos(0, "A", "V") it will return the exact position to draw the "V" to after the "A". It would also work with something like al_get_char_pos(x, "Alleg", "ro") and return the position where to draw the "r"... but usually there would be no need to have more than one letter in either string.

--
"Either help out or stop whining" - Evert

Mark Oates
Member #1,146
March 2001
avatar

My only purpose for drawing char-by-char is to modify the letter spacing.

I think a float al_get_char_pos(ALLEGRO_FONT *font, const char *text, int pos) would work nicely.

One could also invert that and get a cursor position for editing text given an (x,y) location in the string.

gnolam
Member #2,030
March 2002
avatar

Elias said:

I think hinting is patented and therefore not included in Freetype.

The last of the TrueType hinting patents expired in May 2010, at which point even the US versions of FreeType started shipping with the bytecode interpreter enabled by default.
(But yes, hinting and kerning are two completely different concepts. :))

As for OpenType fonts,

The FreeType docs said:

Not all font formats contain kerning information, and not all kerning formats are supported by FreeType; in particular, for TrueType fonts, the API can only access kerning via the ‘kern’ table; OpenType kerning via the ‘GPOS’ table is not supported. You need a higher-level library like Pango or ICU to handle that.

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

Mark Oates
Member #1,146
March 2001
avatar

patent info

gnolam said:

As for OpenType fonts

Awesome. Problem located. Thanks gnolam!

Elias
Member #358
May 2000

I think a float al_get_char_pos(ALLEGRO_FONT *font, const char *text, int pos) would work nicely.

Yeah, I like that. Should be easy to implement. I think it actually could be something like this:

float al_get_char_pos(ALLEGRO_FONT *font, const char *text, int pos) {
   ALLEGRO_USTR *u = al_ustr_new(text);
   int before = al_ustr_offset(u, pos);
   int after = al_ustr_offset(u, pos + 1);
   ALLEGRO_USTR *u2 = al_ustr_dup_substr(u, before, after);
   al_ustr_truncate(u, after);
   float x = al_get_ustr_width(font, u); /* length until after pos */
   x -= al_get_ustr_width(font, u2); /* subtract length of char at pos */
   al_ustr_free(u);
   al_ustr_free(u2);
   return x;
}

--
"Either help out or stop whining" - Evert

Mark Oates
Member #1,146
March 2001
avatar

That works.

I'd like to note in reference to the OP that drawing char by char with this function takes quite a bit longer than drawing by line (due to the two calls to al_get_ustr_width() per call to al_get_char_pos(), though it's much faster than I thought it would be.) So I would recommend cashing the data if you decide to do char-by-char.

drawing by line:
{"name":"603128","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/7\/175a91d38b26a914f4855c5459595acb.png","w":1269,"h":940,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/7\/175a91d38b26a914f4855c5459595acb"}603128
drawing by char with al_get_char_pos(ALLEGRO_FONT *font, const char *text, int pos) for each letter:
{"name":"603127","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/8\/a829ee419f2c1faa18397100e7f08ee7.png","w":1269,"h":940,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/8\/a829ee419f2c1faa18397100e7f08ee7"}603127

The vertical blue line in the profile box is when it affects framerates on my computer.

Peter Wang
Member #23
April 2000

A better interface might be:

float al_get_substr_width(ALLEGRO_FONT *font, const ALLEGRO_USTR *text, int start, int end);

where start/end are counted in code units.
But that's only a convenience over al_ref_ustr.

 1   2 


Go to: