diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index cac4939ed..ce9735f9d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -184,8 +184,8 @@ namespace MWGui MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); // Load fonts - Gui::FontLoader fontLoader (encoding); - fontLoader.loadAllFonts(exportFonts); + mFontLoader.reset(new Gui::FontLoader(encoding, resourceSystem->getVFS())); + mFontLoader->loadAllFonts(exportFonts); //Register own widgets with MyGUI MyGUI::FactoryManager::getInstance().registerFactory("Widget"); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 894c81ec9..16dab08a9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -62,6 +62,11 @@ namespace osgMyGUI class Platform; } +namespace Gui +{ + class FontLoader; +} + namespace MWGui { class WindowBase; @@ -356,6 +361,8 @@ namespace MWGui private: osgMyGUI::Platform* mGuiPlatform; + std::auto_ptr mFontLoader; + bool mConsoleOnlyScripts; std::map mTrackedWindows; diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index 1b61aea90..e579de18f 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -2,8 +2,10 @@ #include -#include -#include +#include +#include + +#include #include #include @@ -11,9 +13,12 @@ #include #include +#include #include +#include + namespace { unsigned long utf8ToUnicode(const std::string& utf8) @@ -123,12 +128,12 @@ namespace return encoder.getUtf8(std::string(1, c)); } - void fail (Ogre::DataStreamPtr file, const std::string& fileName, const std::string& message) + void fail (Files::IStreamPtr file, const std::string& fileName, const std::string& message) { std::stringstream error; error << "Font loading error: " << message; error << "\n File: " << fileName; - error << "\n Offset: 0x" << std::hex << file->tell(); + error << "\n Offset: 0x" << std::hex << file->tellg(); throw std::runtime_error(error.str()); } @@ -137,7 +142,8 @@ namespace namespace Gui { - FontLoader::FontLoader(ToUTF8::FromType encoding) + FontLoader::FontLoader(ToUTF8::FromType encoding, const VFS::Manager* vfs) + : mVFS(vfs) { if (encoding == ToUTF8::WINDOWS_1252) mEncoding = ToUTF8::CP437; @@ -145,19 +151,38 @@ namespace Gui mEncoding = encoding; } + FontLoader::~FontLoader() + { + for (std::vector::iterator it = mTextures.begin(); it != mTextures.end(); ++it) + delete *it; + mTextures.clear(); + + for (std::vector::iterator it = mFonts.begin(); it != mFonts.end(); ++it) + MyGUI::ResourceManager::getInstance().removeByName((*it)->getResourceName()); + mFonts.clear(); + } + void FontLoader::loadAllFonts(bool exportToFile) { - /* - Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups (); - for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it) + const std::map& index = mVFS->getIndex(); + + std::string pattern = "Fonts/"; + mVFS->normalizeFilename(pattern); + + std::map::const_iterator found = index.lower_bound(pattern); + while (found != index.end()) { - Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "*.fnt"); - for (Ogre::StringVector::iterator resource = resourcesInThisGroup->begin(); resource != resourcesInThisGroup->end(); ++resource) + const std::string& name = found->first; + if (name.size() >= pattern.size() && name.substr(0, pattern.size()) == pattern) { - loadFont(*resource, exportToFile); + size_t pos = name.find_last_of('.'); + if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".fnt") == 0) + loadFont(name, exportToFile); } + else + break; + ++found; } - */ } @@ -183,54 +208,62 @@ namespace Gui void FontLoader::loadFont(const std::string &fileName, bool exportToFile) { - Ogre::DataStreamPtr file = Ogre::ResourceGroupManager::getSingleton().openResource(fileName); + Files::IStreamPtr file = mVFS->get(fileName); float fontSize; - if (file->read(&fontSize, sizeof(fontSize)) < sizeof(fontSize)) + file->read((char*)&fontSize, sizeof(fontSize)); + if (!file->good()) fail(file, fileName, "File too small to be a valid font"); int one; - if (file->read(&one, sizeof(int)) < sizeof(int)) + file->read((char*)&one, sizeof(one)); + if (!file->good()) fail(file, fileName, "File too small to be a valid font"); if (one != 1) fail(file, fileName, "Unexpected value"); - if (file->read(&one, sizeof(int)) < sizeof(int)) + file->read((char*)&one, sizeof(one)); + if (!file->good()) fail(file, fileName, "File too small to be a valid font"); if (one != 1) fail(file, fileName, "Unexpected value"); char name_[284]; - if (file->read(name_, sizeof(name_)) < sizeof(name_)) + file->read(name_, sizeof(name_)); + if (!file->good()) fail(file, fileName, "File too small to be a valid font"); std::string name(name_); GlyphInfo data[256]; - if (file->read(data, sizeof(data)) < sizeof(data)) + file->read((char*)data, sizeof(data)); + if (!file->good()) fail(file, fileName, "File too small to be a valid font"); - file->close(); + + file.reset(); // Create the font texture std::string bitmapFilename = "Fonts/" + std::string(name) + ".tex"; - Ogre::DataStreamPtr bitmapFile = Ogre::ResourceGroupManager::getSingleton().openResource(bitmapFilename); + + Files::IStreamPtr bitmapFile = mVFS->get(bitmapFilename); int width, height; - if (bitmapFile->read(&width, sizeof(int)) < sizeof(int)) - fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap"); + bitmapFile->read((char*)&width, sizeof(int)); + bitmapFile->read((char*)&height, sizeof(int)); - if (bitmapFile->read(&height, sizeof(int)) < sizeof(int)) + if (!bitmapFile->good()) fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap"); if (width <= 0 || height <= 0) fail(bitmapFile, bitmapFilename, "Width and height must be positive"); - std::vector textureData; + std::vector textureData; textureData.resize(width*height*4); - if (bitmapFile->read(&textureData[0], width*height*4) < (size_t)(width*height*4)) - fail(bitmapFile, bitmapFilename, "Bitmap does not contain the specified number of pixels"); - bitmapFile->close(); + bitmapFile->read(&textureData[0], width*height*4); + if (!bitmapFile->good()) + fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap"); + bitmapFile.reset(); std::string resourceName; if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic")) @@ -239,24 +272,31 @@ namespace Gui resourceName = "Century Gothic"; else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric")) resourceName = "Daedric"; - else - return; // no point in loading it, since there is no way of using additional fonts std::string textureName = name; - Ogre::Image image; - image.loadDynamicImage(&textureData[0], width, height, Ogre::PF_BYTE_RGBA); - Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual(textureName, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - width, height, 0, Ogre::PF_BYTE_RGBA); - texture->loadImage(image); + + osg::ref_ptr image = new osg::Image; + + unsigned char* bytes = (unsigned char*)calloc(width*height*4, sizeof(unsigned char)); + memcpy(bytes, &textureData[0], textureData.size()); + image->setImage(width, height, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, bytes, osg::Image::USE_MALLOC_FREE); + + osg::ref_ptr texture = new osg::Texture2D; + texture->setImage(image); if (exportToFile) - image.save(resourceName + ".png"); + { + std::cout << "Writing " << resourceName + ".png" << std::endl; + osgDB::writeImageFile(*image, resourceName + ".png"); + } // Register the font with MyGUI MyGUI::ResourceManualFont* font = static_cast( MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont")); + mFonts.push_back(font); + osgMyGUI::OSGTexture* myguiTex = new osgMyGUI::OSGTexture(texture); + mTextures.push_back(myguiTex); + font->setTexture(myguiTex); // We need to emulate loading from XML because the data members are private as of mygui 3.2.0 MyGUI::xml::Document xmlDocument; @@ -390,6 +430,7 @@ namespace Gui if (exportToFile) { + std::cout << "Writing " << resourceName + ".xml" << std::endl; xmlDocument.createDeclaration(); xmlDocument.save(resourceName + ".xml"); } diff --git a/components/fontloader/fontloader.hpp b/components/fontloader/fontloader.hpp index a41506dbb..b92815f13 100644 --- a/components/fontloader/fontloader.hpp +++ b/components/fontloader/fontloader.hpp @@ -1,26 +1,46 @@ -#ifndef MWGUI_FONTLOADER_H -#define MWGUI_FONTLOADER_H +#ifndef OPENMW_COMPONENTS_FONTLOADER_H +#define OPENMW_COMPONENTS_FONTLOADER_H #include +namespace VFS +{ + class Manager; +} + +namespace MyGUI +{ + class ITexture; + class ResourceManualFont; +} + namespace Gui { - /// @brief loads Morrowind's .fnt/.tex fonts for use with MyGUI and Ogre + /// @brief loads Morrowind's .fnt/.tex fonts for use with MyGUI and OSG + /// @note The FontLoader needs to remain in scope as long as you want to use the loaded fonts. class FontLoader { public: - FontLoader (ToUTF8::FromType encoding); + FontLoader (ToUTF8::FromType encoding, const VFS::Manager* vfs); + ~FontLoader(); /// @param exportToFile export the converted fonts (Images and XML with glyph metrics) to files? void loadAllFonts (bool exportToFile); private: ToUTF8::FromType mEncoding; + const VFS::Manager* mVFS; + + std::vector mTextures; + std::vector mFonts; /// @param exportToFile export the converted font (Image and XML with glyph metrics) to files? void loadFont (const std::string& fileName, bool exportToFile); + + FontLoader(const FontLoader&); + void operator=(const FontLoader&); }; }