How to read fonts using RWops

Hi All,

I managed to patch SDL_ttf-2.0.3 and freetype-2.0.4 to read fonts from a
RWops. I don’t know how to do diffs, so I’m pasting the C code here. After
the code for the function TTF_OpenFont in SDL_ttf.c:

-----cut here-----
static unsigned long RWread(FT_Stream stream,unsigned long offset,unsigned
char* buffer,unsigned long count) {
SDL_RWops *rwops;

rwops=(SDL_RWops *)stream->descriptor.pointer;
return SDL_RWread(rwops,(void *)buffer,1,(int)count);


static void RWclose(FT_Stream stream) {
SDL_RWops *rwops;

rwops=(SDL_RWops *)stream->descriptor.pointer;


TTF_Font* TTF_OpenFontRW( SDL_RWops rwops, int ptsize )
FT_Error error;
FT_Face face;
FT_Fixed scale;
FT_Open_Args args;

font = (TTF_Font*) malloc(sizeof *font);
memset((void *)&args,0,sizeof(args)); = (FT_Stream) malloc(sizeof *(;
if ( font == NULL || ) {
        free(; /* free() accepts NULL */
	TTF_SetError( "Out of memory" );
	return NULL;
memset( font, 0, sizeof( *font ) );

/* Open the font and create ancillary data */
SDL_RWseek(rwops,0,SEEK_END); /* should test for errors here... */>size=SDL_RWtell(rwops); /* ...and here... */
SDL_RWseek(rwops,0,SEEK_SET); /* ...and here */>pos=0;>descriptor.pointer=(void *)rwops;>pathname.pointer=NULL;>read=RWread;>close=RWclose;
error = FT_Open_Face( library, &args, 0, &font->face );
if( error ) {
	TTF_SetFTError( "Couldn't load font file", error);
	free( font );
	return NULL;
face = font->face;

/* Make sure that our font face is scalable (global metrics) */
if ( ! FT_IS_SCALABLE(face) ) {
	TTF_SetError("Font face is not scalable");
	TTF_CloseFont( font );
	return NULL;

/* Set the character size and use default DPI (72) */
error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 0, 0 );
if( error ) {
	TTF_SetFTError( "Couldn't set font size", error );
	TTF_CloseFont( font );
	return NULL;

/* Get the scalable font metrics for this font */
scale = face->size->metrics.y_scale;
font->ascent  = FT_CEIL(FT_MulFix(face->bbox.yMax, scale));
font->descent = FT_CEIL(FT_MulFix(face->bbox.yMin, scale));
font->height  = font->ascent - font->descent + /* baseline */ 1;
font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
font->underline_offset =

FT_FLOOR(FT_MulFix(face->underline_position, scale));
font->underline_height =
FT_FLOOR(FT_MulFix(face->underline_thickness, scale));
if ( font->underline_height < 1 ) {
font->underline_height = 1;
printf(“Font metrics:\n”);
printf("\tascent = %d, descent = %d\n",
font->ascent, font->descent);
printf("\theight = %d, lineskip = %d\n",
font->height, font->lineskip);
printf("\tunderline_offset = %d, underline_height = %d\n",
font->underline_offset, font->underline_height);

/* Set the default font style */
font->style = TTF_STYLE_NORMAL;
font->glyph_overhang = face->size->metrics.y_ppem / 10;
/* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
font->glyph_italics = 0.207f;
font->glyph_italics *= font->height;

return font;

-----cut here-----

And insert the TTF_OpenFontRW prototype in SDL_ttf.h.

Well, this didn’t work as I expected and I could see that freetype was
SIGSEGFAULTing during the font load in ftobjs.c at line 61. As I’m using
MingW and Windows and my debugger (gdb) isn’t working well too (it’s
SIGSEGFAULTing also) I couldn’t figure out what exactly was going on but I
could see (with printf’s) that FT_Alloc was receiving a NULL for the memory

So I just changed ftobjs.c to workaround this problem (ok, it is a hack):

line 61: *P=malloc(size);
line 106: Q=realloc(*P,size);
line 132: free(*P);

Now my program crashes during TTF_CloseFont or TTF_Quit when they call
functions from freetype. When I took both functions out of my code
everything worked just fine, besides the memory leaks. I’m going to contact
the people at freetype and see if there is something wrong with the library.

Please note that I’m not asking for help with freetype. The code is here
because it should work (and will with the changes above). As soon as I
figure out what’s happenning I’ll post the fix here.

If anyone tries this with freetype-2.0.5 please tell me if it works.


Andre de Leiradella