As you can know, irrlicht don't allows to load fonts from memory by default, and IGUIEnvironment contains only
Code: Select all
IGUIFont* getFont(const c8* filename)
I've didn't find any solution here, so i decided to make my own one by patching irrlicht.
Irrlicht can emulate files from memory by
Code: Select all
IReadFile* createMemoryReadFile(void* memory, s32 len, const c8* fileName, bool deleteMemoryWhenDropped=false)
Code: Select all
IGUIFont* getFont(irr::io::IReadFile* xmlFile, irr::core::map<irr::core::stringc, irr::io::IReadFile*>& file)
Second one — the map of other files needed for font (textures). The keys of map is file names only (e.g. texture0.png) without any path ("/"). The values of map — texture files, could be emulated from memory.
You can find patch for Irrlicht 1.5 at the bottom of the message, but you shold locate it into root directory (with include, source, doc ...) and apply it via SVN.
Example of usage:
Code: Select all
IGUIEnvironment *env = /* blah blah blah */;
IFileSystem *sys = /* blah blah blah */;
IReadFile* fontXML = sys->createMemoryReadFile(/* pointer to xml file in memory */, /* size of it */, "lucida.xml");
irr::core::map<irr::core::stringc, irr::io::IReadFile*> otherFiles;
otherFiles["lucida0.png"] = sys->createMemoryReadFile(/* pointer to texture file in memory */, /* size of it */, "lucida0.png");
IGUIFont *fnt = env->getFont(fontXML, otherFiles);
PATCH FOR IRRLICTH 1.5:
Code: Select all
Index: include/IGUIEnvironment.h
===================================================================
--- include/IGUIEnvironment.h (revision 4513)
+++ include/IGUIEnvironment.h (working copy)
@@ -11,6 +11,7 @@
#include "EMessageBoxFlags.h"
#include "IEventReceiver.h"
#include "IXMLReader.h"
+#include "irrMap.h"
namespace irr
{
@@ -150,7 +151,16 @@
\return Pointer to the font. Returns 0 if the font could not be loaded.
This pointer should not be dropped. See IReferenceCounted::drop() for
more information. */
- virtual IGUIFont* getFont(const c8* filename) = 0;
+ virtual IGUIFont* getFont(const c8* filename) = 0;
+
+ //! Returns pointer to the font with the specified filereader.
+ /** Loads the font if it was not loaded before.
+ \param xmlFile File contains xml config for font
+ \param files Map of files that should be loaded to font (textures). The key is filenames.
+ \return Pointer to the font. Returns 0 if the font could not be loaded.
+ This pointer should not be dropped. See IReferenceCounted::drop() for
+ more information. */
+ virtual IGUIFont* getFont(irr::io::IReadFile* xmlFile, irr::core::map<irr::core::stringc, irr::io::IReadFile*>& file) = 0;
//! Returns the default built-in font.
/** \return Pointer to the default built-in font.
Index: source/CGUIEnvironment.cpp
===================================================================
--- source/CGUIEnvironment.cpp (revision 4513)
+++ source/CGUIEnvironment.cpp (working copy)
@@ -1287,7 +1287,76 @@
return t;
}
+//! returns the font
+IGUIFont* CGUIEnvironment::getFont(irr::io::IReadFile* xmlFile, irr::core::map<irr::core::stringc, irr::io::IReadFile*>& file)
+{
+ SFont f;
+ IGUIFont* ifont=0;
+ // if file does not have files
+ if (file.isEmpty())
+ {
+ return 0;
+ }
+
+ io::IXMLReader *xml = FileSystem->createXMLReader(xmlFile);
+ 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"vector") == xml->getAttributeValue(L"type"))
+ {
+ t = EGFT_VECTOR;
+ found=true;
+ }
+ else 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, "");
+ ifont = (IGUIFont*)font;
+
+ // load the font
+ if (!font->load(xml, file))
+ {
+ font->drop();
+ font = 0;
+ ifont = 0;
+ }
+ }
+ else if (t==EGFT_VECTOR)
+ {
+ // todo: vector fonts
+ os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.Filename.c_str(), ELL_ERROR);
+
+ }
+ xml->drop();
+ }
+
+ // add to fonts.
+
+ f.Font = ifont;
+ Fonts.push_back(f);
+
+ return ifont;
+}
+
//! returns the font
IGUIFont* CGUIEnvironment::getFont(const c8* filename)
{
Index: source/CGUIEnvironment.h
===================================================================
--- source/CGUIEnvironment.h (revision 4513)
+++ source/CGUIEnvironment.h (working copy)
@@ -73,6 +73,9 @@
//! returns the font
virtual IGUIFont* getFont(const c8* filename);
+ //! returns the font
+ virtual IGUIFont* getFont(irr::io::IReadFile* xmlFile, irr::core::map<irr::core::stringc, irr::io::IReadFile*>& file);
+
//! returns the sprite bank
virtual IGUISpriteBank* getSpriteBank(const c8* filename);
Index: source/CGUIFont.cpp
===================================================================
--- source/CGUIFont.cpp (revision 4513)
+++ source/CGUIFont.cpp (working copy)
@@ -186,7 +186,146 @@
return true;
}
+//! loads a font file from xml
+bool CGUIFont::load(io::IXMLReader* xml, irr::core::map<irr::core::stringc, irr::io::IReadFile*>& files)
+{
+ if (!SpriteBank)
+ return false;
+ while (xml->read())
+ {
+ if (io::EXN_ELEMENT == xml->getNodeType())
+ {
+ if (core::stringw(L"Texture") == xml->getNodeName())
+ {
+ // add a texture
+ core::stringc fn = xml->getAttributeValue(L"filename");
+ u32 i = (u32)xml->getAttributeValueAsInt(L"index");
+ core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
+
+ irr::core::map<irr::core::stringc, irr::io::IReadFile*>::Node* it =
+ files.find(fn);
+
+ if (it)
+ {
+
+ while (i+1 > SpriteBank->getTextureCount())
+ SpriteBank->addTexture(0);
+
+ // disable mipmaps+filtering
+ bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
+ Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
+
+ // load texture
+ SpriteBank->setTexture(i, Driver->getTexture(it->getValue()));
+
+ // set previous mip-map+filter state
+ Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
+
+ // couldn't load texture, abort.
+ if (!SpriteBank->getTexture(i))
+ {
+ os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR);
+ _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
+ return false;
+ }
+ else
+ {
+ // colorkey texture rather than alpha channel?
+ if (alpha == core::stringw("false"))
+ Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0));
+ }
+ }
+ }
+ else if (core::stringw(L"c") == xml->getNodeName())
+ {
+ // adding a character to this font
+ SFontArea a;
+ SGUISpriteFrame f;
+ SGUISprite s;
+ core::rect<s32> rectangle;
+
+ a.underhang = xml->getAttributeValueAsInt(L"u");
+ a.overhang = xml->getAttributeValueAsInt(L"o");
+ a.spriteno = SpriteBank->getSprites().size();
+ s32 texno = xml->getAttributeValueAsInt(L"i");
+
+ // parse rectangle
+ core::stringc rectstr = xml->getAttributeValue(L"r");
+ wchar_t ch = xml->getAttributeValue(L"c")[0];
+
+ const c8 *c = rectstr.c_str();
+ s32 val;
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.UpperLeftCorner.X = val;
+ while (*c == L' ' || *c == L',') c++;
+
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.UpperLeftCorner.Y = val;
+ while (*c == L' ' || *c == L',') c++;
+
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.LowerRightCorner.X = val;
+ while (*c == L' ' || *c == L',') c++;
+
+ val = 0;
+ while (*c >= '0' && *c <= '9')
+ {
+ val *= 10;
+ val += *c - '0';
+ c++;
+ }
+ rectangle.LowerRightCorner.Y = val;
+
+ CharacterMap.insert(ch,Areas.size());
+
+ // make frame
+ f.rectNumber = SpriteBank->getPositions().size();
+ f.textureNumber = texno;
+
+ // add frame to sprite
+ s.Frames.push_back(f);
+ s.frameTime = 0;
+
+ // add rectangle to sprite bank
+ SpriteBank->getPositions().push_back(rectangle);
+ a.width = rectangle.getWidth();
+
+ // add sprite to sprite bank
+ SpriteBank->getSprites().push_back(s);
+
+ // add character to font
+ Areas.push_back(a);
+ }
+ }
+ }
+
+ // set bad character
+ WrongCharacter = getAreaFromCharacter(L' ');
+
+ setMaxHeight();
+
+ return true;
+}
+
void CGUIFont::setMaxHeight()
{
MaxHeight = 0;
Index: source/CGUIFont.h
===================================================================
--- source/CGUIFont.h (revision 4513)
+++ source/CGUIFont.h (working copy)
@@ -48,6 +48,9 @@
//! loads a font from an XML file
bool load(io::IXMLReader* xml);
+ //! loads a font from an XML file and list of texture files
+ bool load(io::IXMLReader* xml, irr::core::map<irr::core::stringc, irr::io::IReadFile*>& files);
+
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const wchar_t* text, const core::rect<s32>& position,
video::SColor color, bool hcenter=false,