Ohloh

GRRLIB 4.2.X Freetype support

In this post i have add information how to add freetype library support to the GRRLIB 4.2.X library

GRRLIB_free_print.h

void GRRLIB_InitFreetype();

void GRRLIB_initTexture(void);

void GRRLIB_Printf2(	int x,
							int y,
							const char *string,
							unsigned int fontSize,
							int color); 

GRRLIB_texImg* GRRLIB_GetTexture(void);

GRRLIB_free_print.c

#include <malloc.h>
#include <stdarg.h>
#include <stdio.h>

#include <grrlib.h>

#include <ft2build.h> /* I presume you have freetype for the Wii installed */
#include FT_FREETYPE_H

#include "font_ttf.h"

static FT_Library ftLibrary;
static FT_Face ftFace;

void *fontTempLayer=NULL;
void *fontTexture=NULL;
GRRLIB_texImg image;

extern  Mtx                  GXmodelView2D;

/* 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) ;

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);
	}
}

void GRRLIB_initTexture(void)
{
   // Clear previous video frame buffer
   if (fontTexture!=NULL) free(fontTexture);

   fontTempLayer = (void*) calloc(1, 640 * 528 * 4);

   if (fontTempLayer == NULL)
   {
	  /* Oops! Something went wrong! */
	  exit(0);
   }
}

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, &delta);
			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 */
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 */
GRRLIB_texImg* 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 * 528 * 4);

	/* Convert the RGBA temp buffer to a format usuable by GX */
	BitmapTo4x4RGBA(fontTempLayer, fontTexture, 640, 528);
	DCFlushRange(fontTexture, 640 * 528 * 4);

	/* The temp buffer is no longer required */
	free(fontTempLayer);
	image.data=fontTexture;
	image.w=640;
	image.h=528;

	return &image;
}

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 */
}

Leave a Reply

 

 

 

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

:D :-) :( :o 8O :? 8) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: