site  contact  subhomenews

TTF text in titlebar gui_engine

January 20, 2023 — BarryK

I posted about starting to analyze how gui_engine works:

https://bkhome.org/news/202301/guiengine-function-hierarchy.html

There are two functions used to draw text on the screen; characterRGBA() and stringRGBA(). These are part of SDL_gfx. The SDL_gfx package is mostly for drawing shapes, such as lines, polygons, circles, etc.; however, it also has some bitmap fonts builtin, of various sizes. The default size is 8x8 pixels. These are basic 256-character ASCI fonts.

These functions call characterRGBA():

g_draw_text(), g_draw_widget_check_box(), g_draw_widget_drop_down_list(), g_draw_window()

This function calls stringRGBA(), to draw text in the window titlebar:

g_draw-window()

Function characterRGBA() draws a character at a time. I am not sure why it is done that way, as that would be less efficient. Anyway, to get going, have converted the call to stringRGBA() to use TTF.

First thing to do is load a font. I put this into 'example.c':

...
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include "gui_engine.h"
#include "example-theme.h"

TTF_Font *ttfFont = NULL;
...
/* Initialize GUI. */
if(g_init_everything() == 0)
{
SDL_FreeSurface(screenSurface);
die("failed to initialize GUI engine");
}

ttfFont = TTF_OpenFont("/usr/share/fonts/TTF/RobotoMono-Bold.ttf", 14);
if( ttfFont == NULL ) die("failed to load ttf font");

g_window *first_window = createDemoWindow(250, 200);
...
SDL_FreeSurface(screenSurface);
TTF_CloseFont(ttfFont);
TTF_Quit();
...

Pretty straightforward. I chose "RobotoMono-Bold", size 14. Note that the "ttfFont" resource has to be removed when the program exits.

Over in 'gui_engine.h':

...
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_gfxPrimitives.h>
#include <string.h>

/* gui engine defines */
/* changing this values can make the windows and widgets look shifted */
#define G_MARGIN 8
#define G_CHAR_W 8
#define G_CHAR_H 12
#define TTF_OFFSET_Y 0
...

And 'gui_engine.c':

...
#include "gui_engine.h"

extern TTF_Font *ttfFont;
SDL_Surface *ttfSurface = NULL;
SDL_Color textColorFG = { 255, 255, 0 };
SDL_Rect offset = { 0, 0 };
...
/* write text in center of title bar */
if(window->flags.close_button)
{
/*stringRGBA(dst, window->x + (window->w - G_WINDOW_CLOSE_BUTTON_WIDTH)/2 - (strlen(temp_string) * G_CHAR_W)/2,
window->y - G_WINDOW_TITLE_BAR_HEIGHT + G_MARGIN, temp_string,
window->color.title_text.r, window->color.title_text.g,
window->color.title_text.b, window->color.title_text.a);*/
textColorFG.r = window->color.title_text.r;
textColorFG.g = window->color.title_text.g;
textColorFG.b = window->color.title_text.b;
ttfSurface = TTF_RenderText_Blended(ttfFont, temp_string, textColorFG);
offset.x = window->x + (window->w - G_WINDOW_CLOSE_BUTTON_WIDTH)/2 - (strlen(temp_string) * G_CHAR_W)/2;
offset.y = window->y - G_WINDOW_TITLE_BAR_HEIGHT + TTF_OFFSET_Y;
SDL_BlitSurface(ttfSurface, NULL, dst, &offset);
SDL_FreeSurface(ttfSurface);
}
else
{
/*stringRGBA(dst, window->x + window->w/2 - (strlen(temp_string) * G_CHAR_W)/2,
window->y - G_WINDOW_TITLE_BAR_HEIGHT + G_MARGIN, temp_string,
window->color.title_text.r, window->color.title_text.g,
window->color.title_text.b, window->color.title_text.a);*/
textColorFG.r = window->color.title_text.r;
textColorFG.g = window->color.title_text.g;
textColorFG.b = window->color.title_text.b;
ttfSurface = TTF_RenderText_Blended(ttfFont, temp_string, textColorFG);
offset.x = window->x + window->w/2 - (strlen(temp_string) * G_CHAR_W)/2;
offset.y = window->y - G_WINDOW_TITLE_BAR_HEIGHT + TTF_OFFSET_Y;
SDL_BlitSurface(ttfSurface, NULL, dst, &offset);
SDL_FreeSurface(ttfSurface);
}
...

...I left in the call to stringRGBA(), commented-out, so we can see how it got replaced.

As I understand it, TTF_RenderText_Blended() reads the TTF text and creates an SDL_Surface with the text antialiased and transparent background. SDL_BlitSurface() writes ttfSurface to the screen (which is a SDL_Surface named "dst").

My understanding also is that once "blitted" to the screen, ttfSurface is no longer required, hence I put in "SDL_FreeSurface(ttfSurface)".

The only slight reservation I have about this, is if the window is dragged, it will go through that entire process again.

Anyway, looking good. Here is a snapshot:

img1

...nice hey! So much prettier than the jagged bitmap text.

There's a nice tutorial on SDL_ttf for SDL v1.2:

http://www.sdltutorials.com/sdl-ttf

Unfortunately, some old SDL v1.2 tutorials have disappeared, good to see this one still online.

Next up, will study the code that calls characterRGBA().   

Tags: easy