TrueType font Support by FreeType Library

A forum to store posts deemed exceptionally wise and useful
Jookia
Posts: 170
Joined: Wed Nov 19, 2008 1:11 am

Post by Jookia »

I'm talking about TrueType fonts, since the TrueType library doesn't want to load from zips.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

OK, I get it now. This is rather hard to do because the loading of those freetype-fonts is happening outside of Irrlicht so you can't just use the comfortable Irrlicht archives. Basically you would have to write a input stream for the freetype library which passes on the content of an Irrlicht archive in some way. Maybe also FT_New_Memory_Face could be used in combination with a MemoryReadFile from Irrlicht somehow. But can't help you there - this is something where I would myself have to invest at least a full day (maybe more) to do that.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Jookia
Posts: 170
Joined: Wed Nov 19, 2008 1:11 am

Post by Jookia »

Well it's kind of essential for this wrapper.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Jookia wrote:Well it's kind of essential for this wrapper.
Why essential? Just don't put fonts in a zip. This is something that might be solved one day, but there's a lot of work to be done before that makes sense (like cleaning up the font-factory patch enough to include it in the engine as first step).

But well, you might try doing it anyway - I haven't really looked into this yet, but it's probably 2 steps: First load the font from zip into a memory file. Then change the tt-font class in a way that allows it to accept memory additional to a filename. Truetype allows using fonts from memory somehow with FT_New_Memory_Face.

Or maybe someone else has fun doing that - it would certainly be a nice addition.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Jookia
Posts: 170
Joined: Wed Nov 19, 2008 1:11 am

Post by Jookia »

Well, right now you have to type in the full directory name anyway, it doesn't search folder archives OR the current directory. That's FreeType library stuff.
amrit36
Posts: 4
Joined: Fri Jul 10, 2009 7:05 am

Post by amrit36 »

hello frnds.. I am compiling Irrlicht1.3 and FREETYPE library.

Everytime i got this ERROR

error C2259: 'irr::gui::CGUITTFont' : cannot instantiate abstract class


help me out of this.
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

amrit36 wrote:hello frnds.. I am compiling Irrlicht1.3 and FREETYPE library.

Everytime i got this ERROR

error C2259: 'irr::gui::CGUITTFont' : cannot instantiate abstract class


help me out of this.
Well, you should definitely update to Irrlicht 1.5, or the SVN. Then you can read up more on the C2259 error here: http://msdn.microsoft.com/en-us/library/zxt206sk.aspx if the problem persists.
TheQuestion = 2B || !2B
amrit36
Posts: 4
Joined: Fri Jul 10, 2009 7:05 am

Post by amrit36 »

i have tested the code with Irrlicht1.5 and also i have tried to solve it, still the error. i am using Visual studio 2008.

plz help me out
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

If you follow the link I posted to help you, then you would see the following, "Code declares an instance of an abstract class or structure", with an even more in-depth description, "You cannot instantiate a class or structure with one or more pure virtual functions." If you don't know what pure virtual functions are, then I suggest you learn some more C++.

Now, with that out of the way. Take a look at CGUITTFont; it inherits from IGUIFont. Since we now know what the error stands for, it obviously is not implementing one or more pure virtual functions from IGUIFont. Let's take a look at the IGUIFont documentation and compare it with the interfaces implemented by CGUITTFont.

CGUITTFont only implements IGUIElement::draw(), IGUIElement::getDimension(), and IGUIElement::getCharacterFromPos(). It still requires IGUIElement::getKerningHeight(), IGUIElement::getKerningWidth(), IGUIElement::setKerningHeight(), and IGUIElement::setKerningWidth(), thus making it an abstract base class.

Now that you have all this information, you should be able to fix your problem.
TheQuestion = 2B || !2B
amrit36
Posts: 4
Joined: Fri Jul 10, 2009 7:05 am

Post by amrit36 »

thanks a lot. I have never done C++ programming before. But i have managed to do this. Thank you very much for your support. :P
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

amrit36 wrote:thanks a lot. I have never done C++ programming before. But i have managed to do this. Thank you very much for your support. :P
No problem, but it's recommended that you know C++ programming before you attempt anything with Irrlicht. It's generally not a fun experience to learn Irrlicht and C++ at the same time.
TheQuestion = 2B || !2B
amrit36
Posts: 4
Joined: Fri Jul 10, 2009 7:05 am

Post by amrit36 »

actually i am having some immediate requirements. so i was testing Irrlicht Engine with freetype rasterizer. well that was really not for fun :? . i think u can understand.

anywayz thanks again.
Jookia
Posts: 170
Joined: Wed Nov 19, 2008 1:11 am

Post by Jookia »

Code: Select all

bool CGUITTFace::load(io::IReadFile* file)
{
    if ( !library )
    {
        if (FT_Init_FreeType( &library ))
        {
            return	false;
        }
    }
	
	void* buffer;
	
	file->read(&buffer, file->getSize());
	
	// typedef unsigned char  FT_Byte;
	if(FT_New_Memory_Face(library, (FT_Byte*)buffer, sizeof(buffer), 0, &face) == true)
		return false;
	
	//if (FT_New_Face( library,filename,0,&face ))
	//{
	//	return	false;
	//}
	return	true;
}

Code: Select all

IGUIFont* CGUIEnvironment::getFont(const c8* filename, u32 size, bool AA, bool TP)
{
	// search existing font

	SFont f;
	IGUIFont* ifont=0;
	if (!filename)
		f.Filename = "";
	else
		f.Filename = filename;

	f.Filename.make_lower();

	core::stringc oldName = f.Filename;

	f.Filename.append(":");
	f.Filename.append(size);

	s32 index = Fonts.binary_search(f);

	if (index != -1)
	{
		if(Fonts[index].Font->getType() != EGFT_FREETYPE)
			return Fonts[index].Font;
			
		// We have to edit the AA and TP on the
		// TrueType fonts.
		
		CGUITTFont* font = (CGUITTFont*)Fonts[index].Font;
		
		font->AntiAlias = AA;
		font->TransParency = TP;
		
		return (IGUIFont*)font;
	}

	f.Filename = oldName;

	// font doesn't exist, attempt to load it

	// does the file exist?

	if (!FileSystem->existFile(filename))
	{
		os::Printer::log("Could not load font because the file does not exist", f.Filename.c_str(), ELL_ERROR);
		return 0;
	}

	io::IXMLReader *xml = FileSystem->createXMLReader(filename);
	if (xml)
	{
		// this is an XML font, but we need to know what type
		EGUI_FONT_TYPE t = EGFT_CUSTOM;

		bool found=false;
		while(xml->read() && !found)
		{
			if (xml->getNodeType() == io::EXN_ELEMENT)
			{
				if (core::stringw(L"font") == xml->getNodeName())
				{
					if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type"))
					{
						t = EGFT_BITMAP;
						found=true;
					}
					else found=true;
				}
			}
		}

		if (t==EGFT_BITMAP)
		{
			CGUIFont* font = new CGUIFont(this, filename);
			ifont = (IGUIFont*)font;
			// change working directory, for loading textures
			core::stringc workingDir = FileSystem->getWorkingDirectory();
			FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.Filename).c_str());

			// load the font
			if (!font->load(xml))
			{
				font->drop();
				font  = 0;
				ifont = 0;
			}
			// change working dir back again
			FileSystem->changeWorkingDirectoryTo(workingDir.c_str());
		}
		xml->drop();
	}


	if (!ifont)
	{
		// The FreeType library is great.
		
		core::stringc name = FileSystem->getAbsolutePath(filename);
		
		CGUITTFace* face = new CGUITTFace;
		
		if(FileSystem->existFile(name.c_str()) == true)
		{
			io::IReadFile* file = FileSystem->createAndOpenFile(name.c_str());
			
			if(face->load(file) == true)
			{
				CGUITTFont* font = new CGUITTFont(Driver);
				
				if(font->attach(face, size) == false)
				{
					font->drop();
					face->drop();
					
					return 0;
				}
				else
				{
					font->AntiAlias = AA;
					font->TransParency = TP;
					
					ifont = (IGUIFont*)font;
				}
			}
			else
			{
				face->drop();
				file->drop();
			}
		}
		else
		{
			face->drop();
			
			CGUIFont* font = new CGUIFont(this, f.Filename.c_str());
			ifont = (IGUIFont*)font;
			if (!font->load(f.Filename.c_str()))
			{
				font->drop();
				return 0;
			}
		}
	}

	// add to fonts.

	f.Filename.append(":");
	f.Filename.append(size);

	f.Font = ifont;
	Fonts.push_back(f);

	return ifont;
}

Code: Select all

#include <irrlicht.h>
	using namespace irr;

#define FONT "C:\\Documents and Settings\\Administrator\\My Documents\\My Projects\\C++\\Vox\\PeerState\\bin\\data\\font.ttf"

int main(void)
{
	IrrlichtDevice* device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 32, false, false, false, 0);
	device->setWindowCaption(core::stringw("PeerState").c_str());
	
	device->getFileSystem()->addFolderFileArchive("data");
	
	video::IVideoDriver* driver  = device->getVideoDriver();
	scene::ISceneManager* smgr   = device->getSceneManager();
	gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment();
	
	guiEnv->getSkin()->setFont(guiEnv->getFont(FONT));
	
	scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS();
	cam->setPosition(core::vector3df(0, 0, 0));
	device->getCursorControl()->setVisible(false);
	
	guiEnv->addStaticText(L"This is an example of <font:font.ttf:18:FF0000>BIG RED TEXT <font:font.ttf:12:000000>and little black text.",
		core::rect<s32>(10,10, 630, 470), true);
	
	int fps = -1;
	core::stringw string;
	
	while(device->run() == true)
	{
		if(driver->getFPS() != fps)
		{
			fps = driver->getFPS();
			
			string = core::stringw("PeerState - ");
			string += fps;
			string += " FPS";
			
			device->setWindowCaption(string.c_str());
		}
		
		driver->beginScene(true, true, video::SColor(255, 128, 25, 25));
		
		smgr->drawAll();
		guiEnv->drawAll();
		
		driver->endScene();
	}
	
	device->drop();
}
Crashes, that's what I have modified.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Just mentioning that I found another problem - getDimensions didn't always return the correct value as it ignored bearing. But I found not out yet how to really fix that, so I've added some workaround in my code. If you have any texts which are clipped because of that (for example the last line in a message-box often lost lower half of characters) then better update. If you still have trouble with characters after updating then add those characters in CGUIFreetypeFont::attach to the workaround section. As always latest version can be found here: http://www.michaelzeilfelder.de/irrlicht.htm#TrueType
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
stefbuet
Competition winner
Posts: 495
Joined: Sun Dec 09, 2007 4:13 pm
Location: france

Post by stefbuet »

Could this problem make some characters disapearing randomly when using multiple time the "attach" for different CGUITTFont objects with the same GUITTFace object?

In fact I just ported the version which worked with Irrlicht 1.4.2 to 1.6 and I had to change some things : firstly I added the setInvisibleCharacters function which became virtual in Irrlicht 1.6. I didn't put anything in this function.

I changed also the draw function: in fact the "text" parameter type changed, it was a const core::stringw and it became a const core::stringw&, so I converted the new parameter to the older type to use the same function :

Code: Select all

void CGUITTFont::draw(const core::stringw& text2,.....) {
const wchar_t* text=text2.c_str();
//...........
}
Now when the same GUIFace is attached to some GUIFonts, some characters are invisible and it's randomly :shock:

Maybe the fact that I changed the stringw& to stringw could make characters invisible ?

CuteAlien, is your version working with Irrlicht 1.6?

Thanks,

Stef.
Post Reply