In this post i have add information how to add freetype library support to GRRLIB 4.0 library
Add the following source code section in the upper part of the GRRLIB 4.0 C file.
#include "font_ttf.h" #define DEFAULT_FIFO_SIZE (256 * 1024) u32 fb = 0; static void *xfb[2] = { NULL, NULL}; GXRModeObj *rmode; void *gp_fifo = NULL; /******************************************************************************/ /**** FREETYPE START ****/ /* This is a very rough implementation if freetype using GRRLIB */ #include /* I presume you have freetype for the Wii installed */ #include FT_FREETYPE_H static FT_Library ftLibrary; static FT_Face ftFace; void *fontTempLayer=NULL; void *fontTexture=NULL; /* Static function prototypes */ static void BitmapTo4x4RGBA(const unsigned char *src, void *dst, const unsigned int width, const unsigned int height); static bool BlitGlyph(FT_Bitmap *bitmap, int offset, int top, int color) ; extern void GRRLIB_InitFreetype(void) { unsigned int error = FT_Init_FreeType(&ftLibrary); if (error) { exit(0); } error = FT_New_Memory_Face(ftLibrary, font_ttf, font_ttf_size, 0, &ftFace); if (error == FT_Err_Unknown_File_Format) { exit(0); } else if (error) { /* Some other error */ exit(0); } } extern void GRRLIB_initTexture(void) { // Clear previous video frame buffer if (fontTexture!=NULL) free(fontTexture); fontTempLayer = (void*) calloc(1, 640 * 480 * 4); if (fontTempLayer == NULL) { /* Oops! Something went wrong! */ exit(0); } } extern void GRRLIB_Printf2(int x, int y, const char *string, unsigned int fontSize, int color) { unsigned int error = 0; int penX = 0; int penY = fontSize; FT_GlyphSlot slot = ftFace->glyph; FT_UInt glyphIndex = 0; FT_UInt previousGlyph = 0; FT_Bool hasKerning = FT_HAS_KERNING(ftFace); error = FT_Set_Pixel_Sizes(ftFace, 0, fontSize); if (error) { /* Failed to set the font size to the requested size. * You probably should set a default size or something. * I'll leave that up to the reader. */ FT_Set_Pixel_Sizes(ftFace, 0, 12); } /* Convert the string to UTF32 */ size_t length = strlen(string); wchar_t *utf32 = (wchar_t*)malloc(length * sizeof(wchar_t)); length = mbstowcs(utf32, string, length); /* Loop over each character, drawing it on to the 4, until the * end of the string is reached, or until the pixel width is too wide */ unsigned int loop = 0; for (loop = 0; loop < length; ++loop) { glyphIndex = FT_Get_Char_Index(ftFace, utf32[ loop ]); /* To the best of my knowledge, none of the other freetype * implementations use kerning, so my method ends up looking * slightly better :) */ if (hasKerning && previousGlyph && glyphIndex) { FT_Vector delta; FT_Get_Kerning(ftFace, previousGlyph, glyphIndex, FT_KERNING_DEFAULT, δ); penX += delta.x >> 6; } error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_RENDER); if (error) { /* Whoops, something went wrong trying to load the glyph * for this character... you should handle this better */ continue; } if (BlitGlyph(&slot->bitmap, penX + slot->bitmap_left+x, penY - slot->bitmap_top+y, color) == true) { /* The glyph was successfully blitted to the buffer, move the pen forwards */ penX += slot->advance.x >> 6; previousGlyph = glyphIndex; } else { /* BlitGlyph returned false, the line must be full */ free(utf32); return; } } free(utf32); } /* Returns true if the character was draw on to the buffer, false if otherwise */ static bool BlitGlyph(FT_Bitmap *bitmap, int offset, int top, int color) { int bitmapWidth = bitmap->width; int bitmapHeight = bitmap->rows; if (offset + bitmapWidth > 640) { /* Drawing this character would over run the buffer, so don't draw it */ return false; } /* Draw the glyph onto the buffer, blitting from the bottom up */ /* CREDIT: Derived from a function by DragonMinded */ unsigned char *p = fontTempLayer; unsigned int y = 0; for (y = 0; y < bitmapHeight; ++y) { int sywidth = y * bitmapWidth; int dywidth = (y + top) * 640; unsigned int column = 0; for (column = 0; column < bitmapWidth; ++column) { unsigned int srcloc = column + sywidth; unsigned int dstloc = ((column + offset) + dywidth) << 2; /* Copy the alpha value for this pixel into the texture buffer */ p[ dstloc + 0 ] = (color & 0xff); p[ dstloc + 1 ] = ((color >> 8) & 0xff); p[ dstloc + 2 ] = ((color >> 16) & 0xff); p[ dstloc + 3 ] = (bitmap->buffer[ srcloc ]); } } return true; } /* Render the text string to a 4x4RGBA texture, return a pointer to this texture */ extern void* GRRLIB_GetTexture(void) { /* Create a new buffer, this time to hold the final texture * in a format suitable for the Wii */ fontTexture = memalign(32, 640 * 480 * 4); /* Convert the RGBA temp buffer to a format usuable by GX */ BitmapTo4x4RGBA(fontTempLayer, fontTexture, 640, 480); DCFlushRange(fontTexture, 640 * 480 * 4); /* The temp buffer is no longer required */ free(fontTempLayer); return fontTexture; } static void BitmapTo4x4RGBA(const unsigned char *src, void *dst, const unsigned int width, const unsigned int height) { unsigned int block = 0; unsigned int i = 0; unsigned int c = 0; unsigned int ar = 0; unsigned int gb = 0; unsigned char *p = (unsigned char*)dst; for (block = 0; block < height; block += 4) { for (i = 0; i < width; i += 4) { /* Alpha and Red */ for (c = 0; c < 4; ++c) { for (ar = 0; ar < 4; ++ar) { /* Alpha pixels */ *p++ = src[(((i + ar) + ((block + c) * width)) * 4) + 3]; /* Red pixels */ *p++ = src[((i + ar) + ((block + c) * width)) * 4]; } } /* Green and Blue */ for (c = 0; c < 4; ++c) { for (gb = 0; gb < 4; ++gb) { /* Green pixels */ *p++ = src[(((i + gb) + ((block + c) * width)) * 4) + 1]; /* Blue pixels */ *p++ = src[(((i + gb) + ((block + c) * width)) * 4) + 2]; } } } /* i */ } /* block */ } inline void GRRLIB_DrawImg2(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], float degrees, float scaleX, f32 scaleY, u8 alpha ) { GXTexObj texObj; GX_InitTexObj(&texObj, data, width,height, GX_TF_RGBA8,GX_CLAMP, GX_CLAMP,GX_FALSE); //GX_InitTexObjLOD(&texObj, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GX_LoadTexObj(&texObj, GX_TEXMAP0); GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); Mtx m,m1,m2, mv; width *=.5; height*=.5; guMtxIdentity (m1); guMtxScaleApply(m1,m1,scaleX,scaleY,1.0); Vector axis =(Vector) {0 , 0, 1 }; guMtxRotAxisDeg (m2, &axis, degrees); guMtxConcat(m2,m1,m); guMtxTransApply(m,m, xpos+width,ypos+height,0); guMtxConcat (GXmodelView2D, m, mv); GX_LoadPosMtxImm (mv, GX_PNMTX0); GX_Begin(GX_QUADS, GX_VTXFMT0,4); GX_Position3f32(-width, -height, 0); GX_Color4u8(0xFF,0xFF,0xFF,alpha); GX_TexCoord2f32(0, 0); GX_Position3f32(width, -height, 0); GX_Color4u8(0xFF,0xFF,0xFF,alpha); GX_TexCoord2f32(1, 0); GX_Position3f32(width, height, 0); GX_Color4u8(0xFF,0xFF,0xFF,alpha); GX_TexCoord2f32(1, 1); GX_Position3f32(-width, height, 0); GX_Color4u8(0xFF,0xFF,0xFF,alpha); GX_TexCoord2f32(0, 1); GX_End(); GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0); GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); } /**** WVDP: FREETYPE END ****/ /****************************************************************************** Add the following part in the GRRLIB.h file /**** WVDP: FREETYPE START ****/ extern void GRRLIB_InitFreetype(); extern void GRRLIB_initTexture(void); extern void GRRLIB_Printf2(int x, int y, const char *string, unsigned int fontSize, int color); extern void* GRRLIB_GetTexture(void); inline void GRRLIB_DrawImg2(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], float degrees, float scaleX, f32 scaleY, u8 alpha ); /**** WVDP: FREETYPE END ****/
For example how to use this extension, please download the RedSquare source code.
Good Luck with it ❗ If you have any questions, please post a comment.
Hi,
I’ve added (and also tryed copiyng from latest redsquare source) these function to my grrlib 4.0 library.
Also I’ve copied lib and includ files from freetype library to the libogc directory.
I compiled my project using freetype and i didn’t get any error.
Just for example I added initialized the font library, then grrlib, then i did a printf2, but the result was a core dump.
Debugging it i noticed the crash occurs in the printf2 line, exactly here:
error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_RENDER);
Seems that when calling FT_Load_Glyph the crash occurs 🙁
Any hint?
This is a great article. I’m new to blogging but still learning. Thanks for the great resource.