TrueType fonts present a higher quality font rendering with the use of font outlines. Each font character is called a glyph. TTF files contain not only outlines but also the glyph's information. Glyph rendering from outlines is much slower than drawing bitmap font characters on screen. This is mainly because these glyphs are being drawn on-the-run and font rendering may be enhanced with antialiasing, which is costly. Because of this, applications using TrueType fonts often cache font glyphs into textures.
The SDL_ttf
library manages the loading of the TrueType font files. Everything you need to use these files is included in the LuaSDL library.
This recipe will deal with loading font glyph in surface object, which you can store into the texture or as a smaller part of the bigger texture—texture atlas.
First, you'll need a TTF file with font data. Let's assume that you already have one called font.ttf
. The next thing you'll need to know is what font size will be used. This is important because the SDL_ttf
library uses this size to set the proper glyph metrics on scalable fonts and to choose the glyph set on nonscalable fonts.
The SDL_ttf
library needs initialization before the first use. You can initialize it with the function call:
SDL.TTF_Init()
The same goes for freeing the resources when you're about to quit the application. You should always call SDL.TTF_Quit()
at the end.
There are four versions of the function you can use to load the SDL.TTF_OpenFont
, SDL.TTF_OpenFontIndex
, SDL.TTF_OpenFontRW
, and SDL_TTF_OpenFontIndexRW
font. The first two use filename to load the font file. The other two use the RWop
object. The functions with the index keyword accept one additional parameter with the font face index. Their specifications are as follows:
SDL.TTF_OpenFont(font_filename, font_size) SDL.TTF_OpenFontIndex(font_filename, font_size, font_face_index) SDL.TTF_OpenFont(rwop, free_src, font_size) SDL.TTF_OpenFontIndex(rwop, free_src, font_size, font_face_index)
The free_src
parameter set to 1 will free the RWop
object after successful load. In this case, the recipe will be using the last version of the function.
First, you need to open the font file:
local rwop = assert(SDL.SDL_RWFromFile("font.ttf","rb"))
Now, you can read the content from the font file:
local font_size = 12 local face_index = 0 local font = assert(SDl.TTF_OpenFontIndexRW(rwop, 1, font_size, face_index))
Now that you have successfully loaded the font file, you can read the font information and glyphs. You'll need the font ascent and descent values to be able to set correct glyph positions.
The next step is to render a glyph. Each glyph contains information about glyph positioning. Without it, the characters wouldn't sit on the baseline because each glyph usually has a different size. To get the glyph positioning information, you need to call SDL.TTF_GlyphMetrics
. Each glyph has different metrics, so you need to obtain this information for each glyph. Fortunately, you can store glyph metrics in the Lua table. You can use the method shown in the following sample:
local glyph_metrics = {} local text = "Hello world ABCDEF" for i=1,#text do local code = string.byte(text, i) if not glyph_metrics[code] then local _, minx, maxx, miny, maxy, advance = SDL.TTF_GlyphMetrics(font, code) glyph_metrics[code] = { minx = minx, maxx = maxx, miny = miny, maxy = maxy, advance = advance, } end end
Glyph metrics are useful if you are rendering texts that change often. If this is not the case, you can safely use the internal SDL_ttf
text renderer to produce surface objects that contain whole text with characters at the right places.
The final part of this recipe is text rendering. There are altogether 12 functions that provide text rendering. Their description is shown in the following table:
Function names |
Description |
---|---|
| |
|
This renders text in UTF8 encoding in solid mode |
|
This renders text in UNICODE encoding in solid mode |
|
This renders a UNICODE glyph in solid mode |
|
This renders text in Latin1 encoding in shaded mode |
|
This renders text in UTF8 encoding in shaded mode |
|
This renders text in UNICODE encoding in shaded mode |
|
This renders a UNICODE glyph in shaded mode |
| |
|
This renders text in UTF8 encoding in blended mode |
|
This renders text in UNICODE encoding in blended mode |
|
This renders a UNICODE glyph in blended mode |
You must have noticed that there are three rendering modes:
You should always use the blended mode with OpenGL. Not only does the text look better, but the process of uploading the texture into the graphic card memory is much easier.
You can draw a single character with any of the SDL.TTF_RenderGlyph_xxx
functions. The following example will be using the blended mode:
local color = SDL.SDL_Color_local() color.r,color.g,color.b = 255,255,255 local glyph_surface = assert(SDL.TTF_RenderGlyph_Blended(font, string.byte("A",1), color))
You can blit glyph_surface
directly to the screen surface object or transfer it into the OpenGL texture. However, be sure to check the pixel format of the glyph_surface
object! The color channel mask can be quite different from what the OpenGL function gl.TexImage
expects. The order of the color channels in glyph_surface
must match the internal texture format! Otherwise, you can expect incomplete texture, invalid texture colors or even segmentation faults (crashes).
Don't forget to call SDL.TTF_CloseFont
to free the font object:
SDL.TTF_CloseFont(font)
Font glyph uses metrics information to maintain the correct glyph placement. A summary of these metrics can be found in the following figure:
The font ascent and descent values can help you with the vertical positioning of characters. Ascent is the distance from the top of the font to the baseline. Descent is the distance from the baseline to the bottom of the font. You can get these two parameters with the SDL.TTF_FontAscent(font)
and SDL.TTF_FontDescent(font)
functions.
3.21.248.162