Click here to Skip to main content
15,867,568 members
Articles / Mobile Apps / iPhone

FreeType on OpenGL ES (iPhone)

Rate me:
Please Sign up or sign in to vote.
4.75/5 (10 votes)
24 Nov 2010CPOL4 min read 86K   3K   27   24
Faster, smarter and better looking fonts rendered with OpenGL ES

Introduction

This project renders fonts using OpenGL ES and the FreeType library. The FreeType library uses font hinting, which makes the fonts look better than your average anti-aliased fonts. This project is primarily designed for the iPhone, however the code is portable and should work on other platforms.

In addition, this code is designed to be efficient. All fonts are bin packed into one texture and draw call batching is implemented.

The standard way to render text in OpenGL is to create a textured quad for each character. You could have a separate texture and quad for each character, but this is very wasteful, because OpenGL textures can only be power of 2 (i.e. 32x32, 64x32,etc) and means there will a lot of unnecessary padding. A better way to do it is to bin pack all the characters into one single texture - known as a texture atlas.

characters bin packed into a texture atlas

Characters bin packed into a 128x128 texture

Another advantage to having everything in the same texture is that it allows you to batch more OpenGL draw calls together. This reduces the workload of the GPU and increases performance.

Using the Code

The principle class is FontAtlas. To prepare a font for use, you must first include the TrueType font (i.e. the .ttf file) as a resource in your project. Then, you call FontAtlas::AddFont with the file name of the font, the desired point size and a list of the characters that you need. You call this function for every font you need, then you call FontAtlas::CreateAtlas(). The FontAtlas class retrieves the size of each character from the FreeType library, then it uses its bin packing algorithm to fit them into a OpenGL ES texture.

Initialising fonts:

C++
const char* szLetters = " !\"#&'()*,-./0123456789:;
<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\_abcdefghijklmnopqrstuvwxyzÁáÉéÍíÑñÓóÚú";

m_pFontAtlas = new FontAtlas();
m_pFontAtlas->AddFont("arial.ttf", 12, szLetters);
m_pFontAtlas->AddFont("times.ttf", 18, szLetters);
m_pFontAtlas->AddFont("times.ttf", 16, szLetters);
m_pFontAtlas->CreateAtlas();

You can then render strings as follows:

C++
FTBitmapFont* pArialFont = m_pFontAtlas->GetFTFont(ARIAL_IX);
pArialFont->DrawString(5, 0, "AV Arial font 12 point", BLACK);

Classes

  • FontAtlas

    This is the principle class. It creates the texture atlas and holds all the FTBitmapFont objects. Each time you call AddFont, a new FTBitmapFont object is created.

  • FTBitmapFont

    FTBitmapFont holds a list of characters and kerning data from the FreeType library. Strings can be rendered via the DrawString method. GetWidth returns the width of a string rendered in the given font.

  • FTBitmapChar

    For each glyph (i.e. character) in the font, there is a FTBitmapChar. This class copies the glyph bitmap into the texture and calculates the texture co-ordinates and vertex dimensions of the character.

  • GLCallBatcher

    This class is responsible for batching the draw calls. Every time a FTBitmapChar wants to draw itself, it calls GLCallBatcher::AddQuad. Instead of drawing directly, GLCallBatcher strings all the quads together in one array and only sends the mesh data to the GPU when RenderCurr is called, or when there a state change is needed. A state change is required, for example, if you change the alpha value, or colour of the text. In this way, the number of draw calls are reduced.

  • TreeNode

    This class is used to implement the bin packing algorithm used to create the texture atlas. This is the algorithm in more detail.

Kerning

You can enable kerning by setting the useKerning flag before the atlas is created:

C++
m_pFontAtlas->SetUseKerning(true); 

Personally, I don't think kerning is worth the performance hit, as you hardly notice the difference in quality.

Compiling FreeType on XCode

The FreeType source is included in the project in the directory OpenGLFont\Classes\freetype-2.4.3. Freetype should really be built as a standalone library, but I didn't have time to do that (exercise left to reader ;) ). I followed the instructions, detailed in INSTALL.ANY in the FreeType documentation. Removing all the bits that I didn't need flattened the directory structure, and disabled the modules that weren't used.

Building the Project

You need to download Boost and unzip it somewhere on your drive. Then set the include paths in xcode to point to the Boost include directory. Also, while you are in there, fix the path for FreeType (i.e. OpenGLFont/Classes/freetype-2.4.3/include/).

Quality

When rendered on a PC, the quality of the FreeType font is quite good, but not quite as good as in other applications (OpenOffice for instance). However, on the iPhone itself, it's a lot better - possibly because of the pixel density of the screen.

History

  • Version 1
  • Version 1.01
    • Fixed bugs: handling character codes > 128
    • Ignore characters that don't exist in font
    • Smarter memory handling

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Astronautz
Spain Spain
After working in the software industry for many years, I've started my own games company that specialises in strategy games for mobile platforms.

Comments and Discussions

 
QuestionMissing OpenGLFont_Prefix.pch file Pin
redhatee20068-Jul-13 4:53
redhatee20068-Jul-13 4:53 
AnswerRe: Missing OpenGLFont_Prefix.pch file Pin
ed welch8-Jul-13 5:16
ed welch8-Jul-13 5:16 
QuestionVBO Pin
mewadale18-Jun-13 4:10
mewadale18-Jun-13 4:10 
AnswerRe: VBO Pin
ed welch19-Jun-13 6:52
ed welch19-Jun-13 6:52 
GeneralRe: VBO Pin
mewadale20-Jun-13 7:32
mewadale20-Jun-13 7:32 
GeneralRe: VBO Pin
mewadale28-Jun-13 1:47
mewadale28-Jun-13 1:47 
GeneralRe: VBO Pin
ed welch30-Jun-13 8:22
ed welch30-Jun-13 8:22 
QuestionCore Text Implementation Pin
David Gish4-Apr-13 19:25
David Gish4-Apr-13 19:25 
AnswerRe: Core Text Implementation Pin
ed welch9-Apr-13 10:30
ed welch9-Apr-13 10:30 
AnswerRe: Core Text Implementation Pin
davemb25-Sep-13 11:35
davemb25-Sep-13 11:35 
QuestionBoost Pin
Halsafar4-Mar-12 11:52
Halsafar4-Mar-12 11:52 
AnswerRe: Boost Pin
ed welch4-Mar-12 12:42
ed welch4-Mar-12 12:42 
QuestionAllocator Class Pin
freeblow12-Sep-11 20:46
freeblow12-Sep-11 20:46 
AnswerRe: Allocator Class Pin
ed welch12-Sep-11 23:20
ed welch12-Sep-11 23:20 
GeneralCompiling in Xcode [modified] Pin
btschumy17-Nov-10 13:52
btschumy17-Nov-10 13:52 
GeneralRe: Compiling in Xcode [modified] Pin
ed welch17-Nov-10 23:21
ed welch17-Nov-10 23:21 
GeneralRe: Compiling in Xcode Pin
btschumy18-Nov-10 4:54
btschumy18-Nov-10 4:54 
GeneralRe: Compiling in Xcode Pin
btschumy18-Nov-10 6:20
btschumy18-Nov-10 6:20 
GeneralRe: Compiling in Xcode Pin
ed welch18-Nov-10 6:25
ed welch18-Nov-10 6:25 
GeneralRe: Compiling in Xcode Pin
btschumy19-Nov-10 6:13
btschumy19-Nov-10 6:13 
GeneralRe: Compiling in Xcode Pin
ed welch19-Nov-10 6:33
ed welch19-Nov-10 6:33 
GeneralGreat Pin
digilancer9-Nov-10 22:58
digilancer9-Nov-10 22:58 
GeneralMy vote of 5 Pin
GPUToaster™9-Nov-10 19:40
GPUToaster™9-Nov-10 19:40 
GeneralMy vote of 5 Pin
Harrison H9-Nov-10 9:28
Harrison H9-Nov-10 9:28 
Who couldn't use this class or find some interest in it?

I look forward to you fleshing out the article and explaining your approach to designing the solution, history on other peoples attempts, etc...!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.