SFML community forums

General => General discussions => Topic started by: Laurent on December 13, 2009, 04:51:12 pm

Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 13, 2009, 04:51:12 pm
Hi

I've written a new implementation for sf::Font in SFML 2, in order to make it more flexible :
- no more need for a fixed character set (glyphs are loaded dynamically on demand)
- no more need for a fixed size (all the requested sizes are handled in a single font)
- proper handling of kerning
- proper handling of line spacing

This should normally have almost no effect on text rendering (once glyphs are in the cache, it works basically the same as before), the only major impact that I can see is an increase in the number of glyph textures produced.

I need the usual feedback : does it crash, is it slow, do you like it, etc. :)

Thanks
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 14, 2009, 10:53:20 am
I did few basic tests to see if new font implementation is more convenient and faster.  I used this code for old sf::Font class: http://paste-it.net/public/qe854f8/ and this for new one: http://paste-it.net/public/r0a9e21/

The results are:
Old sf::Font without styles:
(http://img69.imageshack.us/img69/1761/oldnostyles.th.png) (http://img69.imageshack.us/i/oldnostyles.png/)
FPS: 390-400

Old sf::Font with styles:
(http://img51.imageshack.us/img51/1706/oldwithstyles.th.png) (http://img51.imageshack.us/i/oldwithstyles.png/)
FPS: 100-110

New sf::Font without styles:
(http://img51.imageshack.us/img51/5174/newnostyles.th.png) (http://img51.imageshack.us/i/newnostyles.png/)
FPS: 330-340

New sf::Font with styles:
(http://img51.imageshack.us/img51/281/newwithstyles.th.png) (http://img51.imageshack.us/i/newwithstyles.png/)
FPS: 90-100

In overall:
+ Higher quality of font
+ Kerning
+ Don't need bother about charsets (easier translations)

- Some issues while displaying text with small rotation
- Slower rendering

Questions:
- Why underline is more transparent then font itself.
- Why text with styles is brighter (have invalid colour)

I didn't check how will be displayed small fonts. Which is also very important.

Good job Laurent!
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 11:19:14 am
Hi

Thanks a lot for doing these tests, I apreciate :)

Quote
- Slower rendering

This is not supposed to happen, I'll do some tests to figure out what's wrong.

Quote
- Why underline is more transparent then font itself.
- Why text with styles is brighter (have invalid colour)

This is because of the Bold style. It is currently implemented by rendering 4 times the text with a slight offset in all directions. It results in an incorrect color when alpha is used. Underline is not impacted because it is drawn once even in bold style.
I'm currently not very happy with the way styles are implemented, I'll see if I can find a better solution.

Quote
- Some issues while displaying text with small rotation

2D rendering (especially pixels with integer coordinates) and 1 degree rotations are usually not friends ;)
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 11:59:11 am
I did some tests, and on my machine the kerning calculation is the piece of code that slows the thing down compared to the old version.

Can you deactivate it and try again? To do so, comment the line 246 in src/SFML/Graphics/Text.cpp.
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 14, 2009, 12:23:59 pm
Yep, I uncommented that line and font rendering is even faster then in old version! FPS: 400-410, 90-100. But there is small glitch when rendering with styles, without kerning:
(http://img704.imageshack.us/img704/4880/glitch.th.png) (http://img704.imageshack.us/i/glitch.png/)

After look at 2 letters: VA, I really don't know if kerning is disabled or not, but line is of course uncommented.
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 12:41:21 pm
Quote
But there is small glitch when rendering with styles, without kerning:

This is because I didn't make you comment all the lines involving kerning.
So again, the bold style is messing things up :)

Quote
After look at 2 letters: VA, I really don't know if kerning is disabled or not

You can see that the difference between bold and regular becomes noticeable after the "AV" pair, so yes it is properly disabled on your screenshot.

I'll try to optimize kerning calculations, thanks for your help :)

I may require your help to test the results, because my machine is too fast to make relevant benchmarks.
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 12:48:04 pm
Actually I need you to test one more thing before trying to optimize.

The code to modify is in Font::GetKerning (src/SFML/Graphics/Font.cpp - line 173).

1. First test: replace these lines
Code: [Select]
       FT_UInt index1 = FT_Get_Char_Index(face, first);
        FT_UInt index2 = FT_Get_Char_Index(face, second);

with these ones
Code: [Select]
       FT_UInt index1 = 54;
        FT_UInt index2 = 62;


2. Second test
: restore the code you modified in test 1, and replace these lines
Code: [Select]
       FT_Vector kerning;
        FT_Get_Kerning(face, index1, index2, FT_KERNING_DEFAULT, &kerning);

        // Return the X advance
        return kerning.x >> 6;

with these ones
Code: [Select]
       return 0;


And then tell me if it is FT_Get_Char_Index, FT_Get_Kerning or both that impact performances :)

I found that both impact equally the performances, but like I said it's not very convenient to test at 1000+ FPS.
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 14, 2009, 12:56:12 pm
But do these tests with disabled line 246 in src/SFML/Graphics/Text.cpp?
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 12:59:53 pm
No, uncomment it. Now we're diving deeper into the kerning code ;)
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 14, 2009, 01:11:46 pm
Test 1:
FPS: 380-390 , no changes at all...
Test 2:
FPS: ~410... so there are small changes.
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 01:18:36 pm
Ok I see. So the expensive call is FT_Get_Kerning actually.

Unfortunately, it will be hard to optimize (if not impossible). Kerning informations involve a pair of two characters, which makes way too many combinations to even think about caching it.
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 14, 2009, 01:31:45 pm
I think it's not worth to optimize that thing. If I were you I'd focus on better implementation of styles. Because now they are slow and little buggy. And justify feature would be nice :D
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 02:08:55 pm
I completely agree with that ;)

Except the justify feature. I understand that it is impossible to implement externally, but for now this kind of feature is not planned. But maybe one day. The next thing I'll implement will be different text directions (right-to-left, top-to-bottom, etc.).
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 14, 2009, 03:34:23 pm
Code: [Select]

17. Is it  possible to perform styling (like  oblique, italic, bold,
    underline, etc.) with FreeType?

  Actually, these refer to very different things:

  - Italic  and Bold styles  usually mean  many variations  from the
    'Regular' font.   This is  why you normally  need a  proper font
    file for  each of  these.  For example,  the MS core  font Times
    comes in the following TrueType files:

      TIMES.TTF    Times New Roman Regular
      TIMESI.TTF   Times New Roman Italic
      TIMESB.TTF   Times New Roman Bold
      TIMESBI.TTF  Times New Roman Bold Italic
                   (sometimes named TIMESZ.TTF)

    With FreeType, you simply need the required font file to use it.

  - Oblique style  refers to a  transformation that is applied  to a
    regular font  in order to  make it 'slanted', likes  italics do.
    However,  an  italic font  very  frequently  contains small  but
    important variations that cannot  be produced by this method and
    make the font more appealing.

    Slanting  can  easily  be   done  with  a  transformation  under
    FreeType, with the exact same process as rendering rotated text.
    Please  read  the  "glyphs"   documentation  file  where  it  is
    explained in details.

    Usually, Windows or the  Macintosh produce oblique versions of a
    regular font  when the corresponding italic  TrueType file isn't
    available.   They also stretch  horizontally regular  fonts when
    the  bold one isn't  available.  All  of this  can be  done with
    trivial transformations.

  - Underlining  and stroking, are  not really  part of  the glyphs.
    They're simply lines that are  printed on the glyph after it has
    been rendered.  Each TrueType  file provides, in its OS/2 table,
    which  is  accessible  through  the face  object  properties  in
    FreeType, several  values that define the position  and width of
    those lines, in notional font units.

    If you  want to use them,  you'll have to scale  these values to
    your current instance/point size, then draw the lines yourself.


I really didn't know that there is no support for making bold, italic and underline font faces in freetype 2 library. Now, after some look at your code I finally understand why you use such tricks to render proper text. It would be difficult to do further optimizations in the source code. But I suggest you mentioning in documentation to use specific font files if possible (Arial Bold, Arial Italic) instead of using sf::Text::Style.
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 03:43:15 pm
Even if it was directly provided by FreeType, I probably wouldn't use it anyway. Storing 8 versions (every possible combination of styles) of each glyph would consume too much video memory.

About my plans for improvement:
- italic is ok, the rendering is perfect and involves no extra performance cost
- underline is ok too, it could just be more accurate by requesting the proper offset/thickness values from the font
- bold is clearly too heavy to render and too ugly, I think I can find a better "algorithm"

Quote
But I suggest you mentioning in documentation to use specific font files if possible (Arial Bold, Arial Italic) instead of using sf::Text::Style.

Absolutely, I'll do it when I rewrite the sf::Text documentation.
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 14, 2009, 10:31:51 pm
I fixed Bold and Underlined styles. It's much much better now ;)

And actually FreeType provides functions for bold (FT_Outline_Embold and FT_Bitmap_Embold -- for fonts not supporting vector outlines) that can be used to generate the bold version of a glyph. So the bold style is no longer faked, it is generated and added to the glyphs texture.
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 15, 2009, 05:46:35 pm
That's a great news. I did few tests with different sizes of displayed fonts and styles, and results are really good. Only few FPS lower with styled text. That's how font class should look like form the beginning (I know it wasn't possible ;)). One question although..

What about memory management? I really didn't look at the code. I would spend a lot of time to understand all the concepts, so question is much more convenient.

For example if I use one font, display text size 10 and then use size 50 I bet glyphs are rendered only if I exceed last maximum size? Last one: rendered bold and regular glyphs are held separately?

What are your next plans for sf::String, sf::Text, sf::Font classes ;D?
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 15, 2009, 08:38:16 pm
Quote
For example if I use one font, display text size 10 and then use size 50 I bet glyphs are rendered only if I exceed last maximum size?

No, actually the glyphs are rendered at every requested size. Scaling down a glyph is nearly as ugly as scaling it up ;)
So in this case you will end up with two textures: one containing the glyphs at size 10, and the other for size 50.
If this texture management causes problems, I can add functions to have more control over it (Clear(size), Preload(string, size), etc.). I'll just wait for "real situations" feedback ;)

Quote
Last one: rendered bold and regular glyphs are held separately?

Absolutely. A bold character produces a new glyph, even if the non-bold character is already loaded.

Quote
What are your next plans for sf::String, sf::Text, sf::Font classes ;D?

- sf::String: waiting for more feedback or better ideas; I'm not really satisfied with the current implementation but it will probably stay like that for now
- sf::Text: I'm going to implement text directions (right-to-left, top-to-bottom, etc.)
- sf::Font: I read two excellent articles about text rendering, and tried to improve the text quality in my implementation but I failed so far. I'm also waiting for feedback, but I'm pretty satisfied with the current implementation. It can be optimized regarding texture usage, but I need to tweak sf::Image to do so.
Title: New implementation for sf::Font in SFML 2
Post by: Cierpliwy on December 15, 2009, 08:59:53 pm
Quote
No, actually the glyphs are rendered at every requested size.


So it's nicely done trap ;) For example user want to do effect which looks like:

Code: [Select]
text.SetCharacterSize((frames%100)/100);

And then... oops. My linux suspended in few seconds. No one knows what's going on :) The problem is that this function looks like a "scaling" one. In SFML 1 i used it a lot (but had a different name I think) so others also can misunderstand its meaning.

According to sf::String I will test it for a longer time and say something about it.
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 15, 2009, 10:03:59 pm
Absolutely, and that's why:
- SetCharacterSize now takes an unsigned int instead of a float (it no longer looks like a scale)
- The documentation and tutorials will strongly encourage to use SetScale to scale text :)
Title: New implementation for sf::Font in SFML 2
Post by: K-Bal on December 31, 2009, 05:23:25 pm
Is there still a default font?
Title: New implementation for sf::Font in SFML 2
Post by: Laurent on December 31, 2009, 05:32:52 pm
Of course, and there will still be a default font regardless of the way sf::Font is implemented, because I embed the Arial.ttf file directly in the source code and use LoadFromMemory.
Title: New implementation for sf::Font in SFML 2
Post by: K-Bal on December 31, 2009, 05:41:40 pm
Quote from: "Laurent"
Of course, and there will still be a default font regardless of the way sf::Font is implemented, because I embed the Arial.ttf file directly in the source code and use LoadFromMemory.


Ok, I just had a problem but it was related to the fact that I had a shader program loaded while trying to render stuff ;)