Draw text outline with Freetype

user30088 picture user30088 · Jan 1, 2014 · Viewed 9.2k times · Source

I've implemented FreeType in my program, I can draw text with colors and style (Bold, Italic, Underline).

Now I would like to make an outline effect on my text. How can I do it?

Effect like that
(source: googlecode.com)

  • I've tried to draw the text two times, one larger in black in background and the second in white on foreground, result was wrong.
  • I've tried to draw the text two time, one in bold and the second in one on foreground, here again the result was wrong.

I would like to make a test again : Draw the "background" text in "outline" mode and the foreground text in regular mode. What do you think about it?


(source: googlecode.com)

Answer

Pavulon picture Pavulon · Jan 21, 2015

Rendering text with 2 passes is the key, but you have to position the text correctly. First you should render whole outline and then on top of it render the text.

Rendering the outline:

// initialize stroker, so you can create outline font
FT_Stroker stroker;
FT_Stroker_New(library, &stroker);
//  2 * 64 result in 2px outline
FT_Stroker_Set(stroker, 2 * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
...
// generation of an outline for single glyph:
FT_UInt glyphIndex = FT_Get_Char_Index(face, glyphId);
FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT);
FT_Glyph glyph;
FT_Get_Glyph(face->glyph, &glyph);
FT_Glyph_StrokeBorder(&glyph, stroker, false, true);
FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, nullptr, true);
FT_BitmapGlyph bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyph);
// blit the glyph here on your target surface.
// For positioning use bitmapGlyph->left, bitmapGlyph->top
// For iteration over the glyph data use bitmapGlyph->bitmap.buffer, bitmapGlyph->bitmap.width, bitmapGlyph->bitmap.rows, bitmapGlyph->bitmap.pitch. 

Next you have to render the text itself on the same data you've blitted the outline. Use the code above, but remove the FT_Glyph_StrokeBorder(&glyph, stroker, false, true); line. This way you will have the text on top of an outline.

To achieve this "Cartoon" text effect you will have to do 4 passes: 3 outlines + 1 text. Texturing or applying a gradient should be done during the blitting phase.