Frage

I am stuck at rendering text with FreeType. Especially non-ascii chars give me a headache. After some trial and error I managed to render some text, but my umlauts do not show:

std::string text = "Hauptmenü";
for(std::string::iterator it = text.begin(); it != text.end(); ++it) {
    std::cout << *it;

    FT_Face face = loadFace(faceName);

    FT_Set_Pixel_Sizes(face, 0, fontSize);

    if(FT_Load_Char(face, *it, FT_LOAD_DEFAULT)) {
        std::cout << "Could not load character '" << character << "'" << std::endl;
    }

    FT_Get_Glyph(face->glyph, &glyph);
    FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);

    //render the glyphs to screen and so on
}

Loading the font, getting the glyphs and so on is basically working, but the 'ü' is not rendered. This is what my output looks like:

All characters except the 'ü' get displayed!

All characters except the 'ü' get displayed!

The console output

This is ending up in my console, so I guess something must be wrong with my iteration over the string, as the 'ü' is split up into two chars. The glyph bitmaps I get for the last two chars are both of width and height 0.

How can I fix this?

War es hilfreich?

Lösung

Short version

Read this: http://www.joelonsoftware.com/articles/Unicode.html

Use this: http://www.pango.org/

Long Version

You seem to have some misconceptions about text representation and rendering in general (your use of an abandonware to "check" the text output shows it). Luckily Joel did a pretty decent job at describing the problem: http://www.joelonsoftware.com/articles/Unicode.html

FreeType is able to parse True Type files, and render the glyphs stored in the files. It's not a full-fledged text rendering engine. The font you are using might not even have the glyphs necessary to render the characters you want, you might need to combine different glyphs to produce the desired output.

Of course you are not going to implement the whole Unicode rendering logic yourself, it's a daunting task. You have to use something higher level if you want to just throw "text" at it and get it rendered. At least HarfBuzz, or something on top of it, like Pango or Qt. A good example on how to use Pango+FreeType can be seen in the SDL_Pango library.

Andere Tipps

Your problem is that not all characters can be represented with a single byte. Most international characters (as ü) need two (or more). Your string is basically a array of chars, and the characters that don't fit in a byte will be interpreted as two characters.

One solution is to use std::wstring which basically is a array of wchar_t instead. Your code would then become:

std::wstring text = L"Hauptmenü";
for(std::wstring::iterator it = text.begin(); it != text.end(); ++it) {
    std::wcout << *it;

    FT_Face face = loadFace(faceName);

    FT_Set_Pixel_Sizes(face, 0, fontSize);

    if(FT_Load_Char(face, *it, FT_LOAD_DEFAULT)) {
        std::wcout << L"Could not load character '" << character << L"'" << std::endl;
    }

    FT_Get_Glyph(face->glyph, &glyph);
    FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);

    //render the glyphs to screen and so on
}

There is a lot more to this, and the article DanielKO linked to is a very good start.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top