(C++) How to enable/use anti-aliased font in Irrlicht

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
IPv6
Posts: 188
Joined: Tue Aug 08, 2006 11:58 am

(C++) How to enable/use anti-aliased font in Irrlicht

Post by IPv6 »

Hello!

i recently found that current implementation of GUI font can not use antialiased fonts (= font with transparency and halftones) at all, downgrading such fonts to simple black`n`white pattern at load time (with awful results). After some search i realized that is it by design: anyone who want it should find third-party implementation for bitmap fonts. but this is not really necessary, because IGUIFont already have all infrastructure for that task. there is even no need in patching Irrlicht sources!

But i would ask somebody who can patch sources in SVN to add small flag that will allow to use such fonts internally. see function comments for details

Here is the function that properly loads antialiased font:

Code: Select all

/*
		Current implementation of CGUIFont (irr1.1) is not
		able to use alphablended or antializased fonts.
		This is because of the following lines in the
		readPositions32bit() function
		...
		else
				if (*p == colorBackGround)
					*p = colorBackGroundWithAlphaFalse;
				else
					*p = colorFont;
		...
		All pixels are replaced with font color or font background, no choice :(
		there is a hack that can fix the situation:
		- we asking textture BEFORE IGUIFont and coping all bits into separate memory
		- after IGUIFont corrupts texture, we replacing it back with original bits. This is possible because we can get the same texture by using the same path (look into Irrlicht internal texture manager)
		- after that IGUIFont will use antialiased texture with proper character positions*/

Code: Select all

IGUIFont* AntialiasedFontFixer(IrrlichtDevice *device, const char* szTexturePath)
{
	ITexture* originalTexture=device->getVideoDriver()->getTexture(szTexturePath);
	ECOLOR_FORMAT iSrcFormat=originalTexture->getColorFormat();
	if(iSrcFormat!=ECF_A8R8G8B8){
		// Sorry, only 32bit textures at this time...
		return device->getGUIEnvironment()->getFont(szTexturePath);
	}
	core::dimension2d<s32> size=originalTexture->getOriginalSize();
	s32 iTexSize=size.Width*size.Height*4;/*4 is the size of ECF_A8R8G8B8 pixel */
	BYTE* SrcData=(BYTE*)originalTexture->lock();
	BYTE* SrcDataCopy=new BYTE[iTexSize];
	memcpy(SrcDataCopy,SrcData,iTexSize);
	originalTexture->unlock();
	IGUIFont* fontOut=device->getGUIEnvironment()->getFont(szTexturePath);
	// Now we have to overwrite the same texture (corrupted by IGUIFont) again with original bitmap data
	DWORD dw1=((DWORD*)SrcDataCopy)[0];
	DWORD dw2=((DWORD*)SrcDataCopy)[1];
	DWORD dw3=((DWORD*)SrcDataCopy)[2];
	for(int i=0;i<size.Width*size.Height;i++){
		if((((DWORD*)SrcDataCopy)[i])==dw1 || (((DWORD*)SrcDataCopy)[i])==dw2){
			(((DWORD*)SrcDataCopy)[i])=dw3;
		}
	}
	BYTE* SrcDataAgain=(BYTE*)originalTexture->lock();
	memcpy(SrcDataAgain,SrcDataCopy,iTexSize);
	originalTexture->unlock();
	delete[] SrcDataCopy;
	return fontOut;
}
Usage:
replace device->getGUIEnvironment()->getFont(szTexturePath);
with AntialiasedFontFixer(szTexturePath); in your code

that is all!
Last edited by IPv6 on Sun Aug 27, 2006 7:46 am, edited 2 times in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Shouldn't removing the complete else branch help without the need to copy the textures twice?
IPv6
Posts: 188
Joined: Tue Aug 08, 2006 11:58 am

Post by IPv6 »

you mean by patching sources? Yes, this would be the most right way to add antialiased fonts into irrlicht, but i just do not want to change and recompile the kernel until there is workaround. such overhead is ok for my needs. besides that font loader traverse font bitmap pixel by pixel (!) to find characters positions, extra memcpy +mem allocation is not a big deal.

but i think the better is to add flag into IGUIFont->getFont function, because existing code may rely on current behaviour (for example someone may use this side effect for creating mask or something like this...)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Ah yes, I did not read the code, but it's only too large memcpy so this should be ok. You could also add another IGUIFont class to get rid of all those problems and support your own font file format. But are there any other major formats besides TrueType? Of course you could use fixed width fonts which would use simple setup for texture splits, but for varying width you must have some more information.
IPv6
Posts: 188
Joined: Tue Aug 08, 2006 11:58 am

Post by IPv6 »

i just found that IGUIFont has another drawback, as well as some third party implementations that can be found over net :( i`m talking about non-english characters, non-english charsets (particulary russian charset). i`ve solved the problem and here is the solution and demo project

1) irrFontTool that was supplied with irrlicht does not support non-default charset to be written into generated font. if someone want to generate cyrillic font for example, irrFontTool should be patched to use font charset parameter when calling "CreateFont" API
2) IGUIFont->draw uses wide string as the source, but font bitmap contains non-english characters in the range 128-256 (as typical ASCII font on Windows). so it is impossible to draw wide strings directly. but i wrote function that converts non-english string to "fake" wide string, so IGUIFont is able to pick right character from font texture. it is simple but here it is :)

Code: Select all

core::stringw GUI_A2W(const char* sz)
{
	core::stringw res;
	int l=strlen(sz);
	for(int i=0;i<l;i++){
		UINT c=sz[i];
		WORD wc=MAKEWORD(c,0);
		res.append(wc);
	}
	return res;
}
BTW, this is right (and work good with fixes from the above text) for irrlicht 2d gui in common, not only text scene nodes

demo with src: http://mihd.net/5.780/FlyImage.zip.html

my natural language is russian as i mentioned before :) so sorry for any mistakes :oops:
IPv6
Posts: 188
Joined: Tue Aug 08, 2006 11:58 am

Post by IPv6 »

just for consistency:

here is alternative implementation of IGUIFont (based on original one) with two improvements:
- it can work with full-color/alpha blended font images (no 2-color limitation anymore)
- it has "setScale" method. Can be used to make resolution-independent UI (just set scale at application startup according to current resolution, all dimensions, etc, will use scaled values. No need in repositioning UI elements for different resolutions anymore) or just to get special effects over text nodes, etc.

link:
http://rapidshare.com/files/2067705/GUIFontX.zip.html
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Splendid stuff. Can I suggest that you submit this to the tracker? This functionality should definitely be in Irrlicht.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

I'm planning on revamping GUIFonts so they can use unicode properly, starting with a unicode font tool (which as you can see is currently giving me no end of trouble). resizable, antialiased, unicode fonts may arrive before Irrlicht 1.3 if you're lucky :)
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Are you planning in revamping Irrlicht to use unicode [UTF-8, UTF-16 or UTF-32] properly, or just the fonts?
IPv6
Posts: 188
Joined: Tue Aug 08, 2006 11:58 am

Post by IPv6 »

bitplane wrote:I'm planning on revamping GUIFonts so they can use unicode properly ... resizable, antialiased, unicode fonts may arrive before Irrlicht 1.3 if you're lucky :)
Nice to hear this!
it is a pitty that current implementation does not support such basic things like normal (colorful) fonts and sizing on the fly. After several attempts to use Irrlicht`s gui part for my game i gived up and rebuild this stuff based on billboards instead of 2d graphics... last thing that convinced me to give up was disabled (in set2drenderstates) antialiasing (any anitaliasing!!!) for 2d operations which make any attempt to use draw2d useless. Of cource it can be changed by tweaking sources, but i don`t want to tweak them since i don`t want to do this with every new version of irrlicht :)
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

vitek wrote:Are you planning in revamping Irrlicht to use unicode [UTF-8, UTF-16 or UTF-32] properly, or just the fonts?
Hmm sorry I didn't make that very clear, I'm just making a new font tool which converts unicode fonts to bitmaps and xml, and a font loader which loads them back into wchar_t's. I'm not going to go so far as making a portable unicode replacement for wchar_t or anything
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Post Reply