int TTF_Init( void ) { int status = 0; if ( ! TTF_initialized ) { FT_Error error = FT_Init_FreeType( &library ); if ( error ) { TTF_SetFTError("Couldn't init FreeType engine", error); status = -1; } } if ( status == 0 ) { ++TTF_initialized; } return status; }
TTF_Font * TTF_OpenFontIndexRW(SDL_RWops * src, int freesrc, int ptsize, long index) { TTF_Font *font; FT_Error error; FT_Face face; FT_Fixed scale; FT_Stream stream; int position; if(!TTF_initialized) { TTF_SetError("Library not initialized"); return NULL; } /* Check to make sure we can seek in this stream */ position = SDL_RWtell(src); if(position < 0) { TTF_SetError("Can't seek in stream"); return NULL; } font = (TTF_Font *) malloc(sizeof *font); if(font == NULL) { TTF_SetError("Out of memory"); return NULL; } memset(font, 0, sizeof(*font)); font->src = src; font->freesrc = freesrc; stream = (FT_Stream) malloc(sizeof(*stream)); if(stream == NULL) { TTF_SetError("Out of memory"); TTF_CloseFont(font); return NULL; } memset(stream, 0, sizeof(*stream)); /* 090303 Chase - Newer FT2 version sets this internally so we don't have to. (Can't anyway, Don't have a definition for FT_Library) */ // stream->memory = library->memory; stream->read = RWread; stream->descriptor.pointer = src; stream->pos = (unsigned long) position; SDL_RWseek(src, 0, SEEK_END); stream->size = (unsigned long) (SDL_RWtell(src) - position); SDL_RWseek(src, position, SEEK_SET); font->args.flags = FT_OPEN_STREAM; font->args.stream = stream; error = FT_Open_Face(library, &font->args, index, &font->face); if(error) { TTF_SetFTError("Couldn't load font file", error); TTF_CloseFont(font); return NULL; } face = font->face; /* Make sure that our font face is scalable (global metrics) */ if(FT_IS_SCALABLE(face)) { /* 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)); } else { /* Non-scalable font case. ptsize determines which family * or series of fonts to grab from the non-scalable format. * It is not the point size of the font. * */ if(ptsize >= font->face->num_fixed_sizes) ptsize = font->face->num_fixed_sizes - 1; font->font_size_family = ptsize; error = FT_Set_Pixel_Sizes(face, face->available_sizes[ptsize].height, face->available_sizes[ptsize].width); /* With non-scalale fonts, Freetype2 likes to fill many of the * font metrics with the value of 0. The size of the * non-scalable fonts must be determined differently * or sometimes cannot be determined. * */ font->ascent = face->available_sizes[ptsize].height; font->descent = 0; font->height = face->available_sizes[ptsize].height; font->lineskip = FT_CEIL(font->ascent); font->underline_offset = FT_FLOOR(face->underline_position); font->underline_height = FT_FLOOR(face->underline_thickness); } if(font->underline_height < 1) { font->underline_height = 1; } #ifdef DEBUG_FONTS 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); #endif /* 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; }
TTF_Font* TTF_OpenFontIndexRW( FILE* src, int freesrc, int ptsize, long index ) { TTF_Font* font; FT_Error error; FT_Face face; FT_Fixed scale; FT_Stream stream; FT_CharMap found; int position, i; if ( ! TTF_initialized ) { TTF_SetError( "Library not initialized" ); return NULL; } /* Check to make sure we can seek in this stream */ position = ftell(src); if ( position < 0 ) { TTF_SetError( "Can't seek in stream" ); return NULL; } font = (TTF_Font*) malloc(sizeof *font); if ( font == NULL ) { TTF_SetError( "Out of memory" ); return NULL; } memset(font, 0, sizeof(*font)); font->src = src; font->freesrc = freesrc; stream = (FT_Stream)malloc(sizeof(*stream)); if ( stream == NULL ) { TTF_SetError( "Out of memory" ); TTF_CloseFont( font ); return NULL; } memset(stream, 0, sizeof(*stream)); stream->read = ft_read; stream->descriptor.pointer = src; stream->pos = (unsigned long)position; fseek(src, 0, SEEK_END); stream->size = (unsigned long)(ftell(src) - position); fseek(src, position, SEEK_SET); font->args.flags = FT_OPEN_STREAM; font->args.stream = stream; error = FT_Open_Face( library, &font->args, index, &font->face ); if( error ) { TTF_SetFTError( "Couldn't load font file", error ); TTF_CloseFont( font ); return NULL; } face = font->face; /* Set charmap for loaded font */ found = 0; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap charmap = face->charmaps[i]; /* Windows Unicode */ if ((charmap->platform_id == 3 && charmap->encoding_id == 1) /* Windows Symbol */ || (charmap->platform_id == 3 && charmap->encoding_id == 0) /* ISO Unicode */ || (charmap->platform_id == 2 && charmap->encoding_id == 1) /* Apple Unicode */ || (charmap->platform_id == 0)) { found = charmap; break; } } if ( found ) { /* If this fails, continue using the default charmap */ FT_Set_Charmap(face, found); } /* Make sure that our font face is scalable (global metrics) */ if ( FT_IS_SCALABLE(face) ) { /* 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->ascender, scale)); font->descent = FT_CEIL(FT_MulFix(face->descender, 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)); } else { /* Non-scalable font case. ptsize determines which family * or series of fonts to grab from the non-scalable format. * It is not the point size of the font. * */ if ( ptsize >= font->face->num_fixed_sizes ) ptsize = font->face->num_fixed_sizes - 1; font->font_size_family = ptsize; error = FT_Set_Pixel_Sizes( face, face->available_sizes[ptsize].height, face->available_sizes[ptsize].width ); /* With non-scalale fonts, Freetype2 likes to fill many of the * font metrics with the value of 0. The size of the * non-scalable fonts must be determined differently * or sometimes cannot be determined. * */ font->ascent = face->available_sizes[ptsize].height; font->descent = 0; font->height = face->available_sizes[ptsize].height; font->lineskip = FT_CEIL(font->ascent); font->underline_offset = FT_FLOOR(face->underline_position); font->underline_height = FT_FLOOR(face->underline_thickness); } if ( font->underline_height < 1 ) { font->underline_height = 1; } #ifdef DEBUG_FONTS 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); printf("\tunderline_top_row = %d, strikethrough_top_row = %d\n", TTF_underline_top_row(font), TTF_strikethrough_top_row(font)); #endif /* Initialize the font face style */ font->face_style = TTF_STYLE_NORMAL; if ( font->face->style_flags & FT_STYLE_FLAG_BOLD ) { font->face_style |= TTF_STYLE_BOLD; } if ( font->face->style_flags & FT_STYLE_FLAG_ITALIC ) { font->face_style |= TTF_STYLE_ITALIC; } /* Set the default font style */ font->style = font->face_style; font->outline = 0; font->kerning = 1; 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; }