Simple truetype font library for SDL2

Hi,

SDL uses the SDL_ttf library for font rendering. The engine of this lib is the freetype lib, which is fine until you have to cross-compile for Android. This freetype lib consists of a huge number of C files, that must be compiled apart from the Android NDK environment because no Android.mk files are provided.

There is an alternative. A clever guy called Sean Barrett has written a parser and renderer for truetype fonts. It consists of one file (http://nothings.org/stb/stb_truetype.h), containing everything you need: a manual, examples, header file and C code.

From the examples I created a small demo program, listed hereunder.
If you call it test-stbtt.c it can be compiled as follows:
gcc test-stbtt.c -o test-stbtt $(sdl2-config --cflags) $(sdl2-config --libs) -lm

It can be run with 0, 1, 2 or 3 options, and will display a black text in a white window. Notice that there is a hard-coded path to a ttf spec file, modify this as needed.

I did’nt use all provided refinements in this demo program. Notice that the SDL.h file is included after the stb_truetype.h, that’s because some big- and small endian magic occurs, which might get disturbed by #define statements in SDL.h. The characters that are displayed are not cached, so a big speed-up would still be possible.

wboe

Code:
#define STB_TRUETYPE_IMPLEMENTATION
#include “stb_truetype.h”

#include <SDL.h>

int main(int argc, char **argv) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf(“Init problem: %s\n”,SDL_GetError()); exit(1); }
SDL_Window *window = SDL_CreateWindow(“test-stbtt”, 100,100,200,100, SDL_WINDOW_SHOWN);
if (!window) { printf("%s\n",SDL_GetError()); SDL_Quit(); }
SDL_Renderer *renderer=SDL_CreateRenderer(window, -1,SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(renderer,0xff,0xff,0xff,0xff);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);

stbtt_fontinfo font;
unsigned char *bitmap=0;
const char *text=(argc > 1 ? argv[1] : “Hallo!”);
int s = (argc > 2 ? atoi(argv[2]) : 20);

FILE *ff=fopen(argc > 3 ? argv[3] : “/usr/share/fonts/google-droid/DroidSans.ttf”,“rb”);
if (!ff) { puts(“font file not found”); exit(1); }
fseek(ff,0,SEEK_END);
int fsize=ftell(ff);
rewind(ff);
char ttf_buffer[fsize];
fread(ttf_buffer, 1,fsize,ff);

stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
float scale=stbtt_ScaleForPixelHeight(&font, s);
int ascent,
descent;
stbtt_GetFontVMetrics(&font,&ascent,&descent,0);

int ind,
advance,
x0,y0,
h,w,
xpos=10,
ypos=10+scaleascent;
printf(“ascent=%d descent=%d linedist=%d\n”,(int)(scale
ascent),(int)(scale*descent),(int)(scale * (ascent-descent)));
for (ind=0;text[ind];++ind) {
bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), text[ind], &w, &h, 0,0);
stbtt_GetCodepointHMetrics(&font, text[ind], &advance, 0);
stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ind], scale,scale,0,0, &x0,&y0,0,0);

  int i,j,
      x=xpos,
      y=ypos;
  for (j=0; j < h; ++j) {
     for (i=0; i < w; ++i) {
        if (bitmap[j*w+i]) {
          SDL_SetRenderDrawColor(renderer,0,0,0,bitmap[j*w+i]);
          SDL_RenderDrawPoint(renderer,x+x0,y+y0);
        }
        ++x;
     }
     x=xpos;
     ++y;
  }
  stbtt_FreeBitmap(bitmap,0);
  if (!text[ind+1]) break;
  xpos += scale*advance;

}
SDL_RenderPresent(renderer);
SDL_Event event;
while (1)
while(SDL_PollEvent(&event))
if (event.type==SDL_QUIT) { SDL_Quit(); exit(0); }
return 0;
}

Because of the open nature of the license, what I’d recommend (and this is
something that I may do myself anyway) is to add some code to support
SDL_RWops, and write an official SDL port of the library. Once that’s
done, the community will have a chance to see it in action with SDL. I
don’t think this needs to be a replacement for SDL_ttf, either - if it
works, it’s just another option.

The more I read through the code, the more I get this impression that I’ve
looked at this before, and maybe it was on this mailing list a few years
ago? Anyway, good find, and nice example of it alongside SDL :slight_smile:

-AlexOn Mon, Oct 15, 2012 at 4:35 AM, wboe <w.boeke at upcmail.nl> wrote:

**
Hi,

SDL uses the SDL_ttf library for font rendering. The engine of this lib is
the freetype lib, which is fine until you have to cross-compile for
Android. This freetype lib consists of a huge number of C files, that must
be compiled apart from the Android NDK environment because no Android.mk
files are provided.

There is an alternative. A clever guy called Sean Barrett has written a
parser and renderer for truetype fonts. It consists of one file (
http://nothings.org/stb/stb_truetype.h), containing everything you need:
a manual, examples, header file and C code.

From the examples I created a small demo program, listed hereunder.
If you call it test-stbtt.c it can be compiled as follows:
gcc test-stbtt.c -o test-stbtt $(sdl2-config --cflags) $(sdl2-config
–libs) -lm

It can be run with 0, 1, 2 or 3 options, and will display a black text in
a white window. Notice that there is a hard-coded path to a ttf spec file,
modify this as needed.

I did’nt use all provided refinements in this demo program. Notice that
the SDL.h file is included after the stb_truetype.h, that’s because some
big- and small endian magic occurs, which might get disturbed by #define
statements in SDL.h. The characters that are displayed are not cached, so a
big speed-up would still be possible.

wboe

Code:

#define STB_TRUETYPE_IMPLEMENTATION
#include “stb_truetype.h”

#include **

int main(int argc, char **argv) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf(“Init problem:
%s\n”,SDL_GetError()); exit(1); }
SDL_Window *window = SDL_CreateWindow(“test-stbtt”, 100,100,200,100,
SDL_WINDOW_SHOWN);
if (!window) { printf("%s\n",SDL_GetError()); SDL_Quit(); }
SDL_Renderer *renderer=SDL_CreateRenderer(window,
-1,SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(renderer,0xff,0xff,0xff,0xff);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);

stbtt_fontinfo font;
unsigned char *bitmap=0;
const char *text=(argc > 1 ? argv[1] : “Hallo!”);
int s = (argc > 2 ? atoi(argv[2]) : 20);

FILE *ff=fopen(argc > 3 ? argv[3] :
"/usr/share/fonts/google-droid/DroidSans.ttf",“rb”);
if (!ff) { puts(“font file not found”); exit(1); }
fseek(ff,0,SEEK_END);
int fsize=ftell(ff);
rewind(ff);
char ttf_buffer[fsize];
fread(ttf_buffer, 1,fsize,ff);

stbtt_InitFont(&font, ttf_buffer,
stbtt_GetFontOffsetForIndex(ttf_buffer,0));
float scale=stbtt_ScaleForPixelHeight(&font, s);
int ascent,
descent;
stbtt_GetFontVMetrics(&font,&ascent,&descent,0);

int ind,
advance,
x0,y0,
h,w,
xpos=10,
ypos=10+scaleascent;
printf(“ascent=%d descent=%d
linedist=%d\n”,(int)(scale
ascent),(int)(scale*descent),(int)(scale *
(ascent-descent)));
for (ind=0;text[ind];++ind) {
bitmap = stbtt_GetCodepointBitmap(&font,
0,stbtt_ScaleForPixelHeight(&font, s), text[ind], &w, &h, 0,0);
stbtt_GetCodepointHMetrics(&font, text[ind], &advance, 0);
stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ind],
scale,scale,0,0, &x0,&y0,0,0);

  int i,j,
      x=xpos,
      y=ypos;
  for (j=0; j < h; ++j) {
     for (i=0; i < w; ++i) {
        if (bitmap[j*w+i]) {
          SDL_SetRenderDrawColor(renderer,0,0,0,bitmap[j*w+i]);
          SDL_RenderDrawPoint(renderer,x+x0,y+y0);
        }
        ++x;
     }
     x=xpos;
     ++y;
  }
  stbtt_FreeBitmap(bitmap,0);
  if (!text[ind+1]) break;
  xpos += scale*advance;

}
SDL_RenderPresent(renderer);
SDL_Event event;
while (1)
while(SDL_PollEvent(&event))
if (event.type==SDL_QUIT) { SDL_Quit(); exit(0); }
return 0;
}


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SFML has internal font rendering, if this truetype rendering added in SDL,
I think it would very usefull, we don’t need freetype again, especially for
iOS and Android.

regards

Afaik there is no problem in compiling Freetype for Android.
You can find the Android.mk we use every day here:
https://code.google.com/p/hedgewars/source/browse/#hg%2Fmisc%2Flibfreetype

VittorioOn Mon, Oct 15, 2012 at 10:35 AM, wboe <w.boeke at upcmail.nl> wrote:

**
Hi,

SDL uses the SDL_ttf library for font rendering. The engine of this lib is
the freetype lib, which is fine until you have to cross-compile for
Android. This freetype lib consists of a huge number of C files, that must
be compiled apart from the Android NDK environment because no Android.mk
files are provided.

There is an alternative. A clever guy called Sean Barrett has written a
parser and renderer for truetype fonts. It consists of one file (
http://nothings.org/stb/stb_truetype.h), containing everything you need:
a manual, examples, header file and C code.

From the examples I created a small demo program, listed hereunder.
If you call it test-stbtt.c it can be compiled as follows:
gcc test-stbtt.c -o test-stbtt $(sdl2-config --cflags) $(sdl2-config
–libs) -lm

It can be run with 0, 1, 2 or 3 options, and will display a black text in
a white window. Notice that there is a hard-coded path to a ttf spec file,
modify this as needed.

I did’nt use all provided refinements in this demo program. Notice that
the SDL.h file is included after the stb_truetype.h, that’s because some
big- and small endian magic occurs, which might get disturbed by #define
statements in SDL.h. The characters that are displayed are not cached, so a
big speed-up would still be possible.

wboe

Code:

#define STB_TRUETYPE_IMPLEMENTATION
#include “stb_truetype.h”

#include **

int main(int argc, char **argv) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf(“Init problem:
%s\n”,SDL_GetError()); exit(1); }
SDL_Window *window = SDL_CreateWindow(“test-stbtt”, 100,100,200,100,
SDL_WINDOW_SHOWN);
if (!window) { printf("%s\n",SDL_GetError()); SDL_Quit(); }
SDL_Renderer *renderer=SDL_CreateRenderer(window,
-1,SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(renderer,0xff,0xff,0xff,0xff);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);

stbtt_fontinfo font;
unsigned char *bitmap=0;
const char *text=(argc > 1 ? argv[1] : “Hallo!”);
int s = (argc > 2 ? atoi(argv[2]) : 20);

FILE *ff=fopen(argc > 3 ? argv[3] :
"/usr/share/fonts/google-droid/DroidSans.ttf",“rb”);
if (!ff) { puts(“font file not found”); exit(1); }
fseek(ff,0,SEEK_END);
int fsize=ftell(ff);
rewind(ff);
char ttf_buffer[fsize];
fread(ttf_buffer, 1,fsize,ff);

stbtt_InitFont(&font, ttf_buffer,
stbtt_GetFontOffsetForIndex(ttf_buffer,0));
float scale=stbtt_ScaleForPixelHeight(&font, s);
int ascent,
descent;
stbtt_GetFontVMetrics(&font,&ascent,&descent,0);

int ind,
advance,
x0,y0,
h,w,
xpos=10,
ypos=10+scaleascent;
printf(“ascent=%d descent=%d
linedist=%d\n”,(int)(scale
ascent),(int)(scale*descent),(int)(scale *
(ascent-descent)));
for (ind=0;text[ind];++ind) {
bitmap = stbtt_GetCodepointBitmap(&font,
0,stbtt_ScaleForPixelHeight(&font, s), text[ind], &w, &h, 0,0);
stbtt_GetCodepointHMetrics(&font, text[ind], &advance, 0);
stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ind],
scale,scale,0,0, &x0,&y0,0,0);

  int i,j,
      x=xpos,
      y=ypos;
  for (j=0; j < h; ++j) {
     for (i=0; i < w; ++i) {
        if (bitmap[j*w+i]) {
          SDL_SetRenderDrawColor(renderer,0,0,0,bitmap[j*w+i]);
          SDL_RenderDrawPoint(renderer,x+x0,y+y0);
        }
        ++x;
     }
     x=xpos;
     ++y;
  }
  stbtt_FreeBitmap(bitmap,0);
  if (!text[ind+1]) break;
  xpos += scale*advance;

}
SDL_RenderPresent(renderer);
SDL_Event event;
while (1)
while(SDL_PollEvent(&event))
if (event.type==SDL_QUIT) { SDL_Quit(); exit(0); }
return 0;
}


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org