Port FontLoader - requires MyGUI patch from https://github.com/MyGUI/mygui/pull/69

c++11
scrawl 10 years ago
parent a59940a2c7
commit 6afb0e43ef

@ -184,8 +184,8 @@ namespace MWGui
MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag);
// Load fonts // Load fonts
Gui::FontLoader fontLoader (encoding); mFontLoader.reset(new Gui::FontLoader(encoding, resourceSystem->getVFS()));
fontLoader.loadAllFonts(exportFonts); mFontLoader->loadAllFonts(exportFonts);
//Register own widgets with MyGUI //Register own widgets with MyGUI
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget");

@ -62,6 +62,11 @@ namespace osgMyGUI
class Platform; class Platform;
} }
namespace Gui
{
class FontLoader;
}
namespace MWGui namespace MWGui
{ {
class WindowBase; class WindowBase;
@ -356,6 +361,8 @@ namespace MWGui
private: private:
osgMyGUI::Platform* mGuiPlatform; osgMyGUI::Platform* mGuiPlatform;
std::auto_ptr<Gui::FontLoader> mFontLoader;
bool mConsoleOnlyScripts; bool mConsoleOnlyScripts;
std::map<MyGUI::Window*, std::string> mTrackedWindows; std::map<MyGUI::Window*, std::string> mTrackedWindows;

@ -2,8 +2,10 @@
#include <stdexcept> #include <stdexcept>
#include <OgreResourceGroupManager.h> #include <osg/Image>
#include <OgreTextureManager.h> #include <osg/Texture2D>
#include <osgDB/WriteFile>
#include <MyGUI_ResourceManager.h> #include <MyGUI_ResourceManager.h>
#include <MyGUI_FontManager.h> #include <MyGUI_FontManager.h>
@ -11,9 +13,12 @@
#include <MyGUI_XmlDocument.h> #include <MyGUI_XmlDocument.h>
#include <MyGUI_FactoryManager.h> #include <MyGUI_FactoryManager.h>
#include <components/vfs/manager.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/myguiplatform/myguitexture.hpp>
namespace namespace
{ {
unsigned long utf8ToUnicode(const std::string& utf8) unsigned long utf8ToUnicode(const std::string& utf8)
@ -123,12 +128,12 @@ namespace
return encoder.getUtf8(std::string(1, c)); 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; std::stringstream error;
error << "Font loading error: " << message; error << "Font loading error: " << message;
error << "\n File: " << fileName; 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()); throw std::runtime_error(error.str());
} }
@ -137,7 +142,8 @@ namespace
namespace Gui namespace Gui
{ {
FontLoader::FontLoader(ToUTF8::FromType encoding) FontLoader::FontLoader(ToUTF8::FromType encoding, const VFS::Manager* vfs)
: mVFS(vfs)
{ {
if (encoding == ToUTF8::WINDOWS_1252) if (encoding == ToUTF8::WINDOWS_1252)
mEncoding = ToUTF8::CP437; mEncoding = ToUTF8::CP437;
@ -145,19 +151,38 @@ namespace Gui
mEncoding = encoding; mEncoding = encoding;
} }
FontLoader::~FontLoader()
{
for (std::vector<MyGUI::ITexture*>::iterator it = mTextures.begin(); it != mTextures.end(); ++it)
delete *it;
mTextures.clear();
for (std::vector<MyGUI::ResourceManualFont*>::iterator it = mFonts.begin(); it != mFonts.end(); ++it)
MyGUI::ResourceManager::getInstance().removeByName((*it)->getResourceName());
mFonts.clear();
}
void FontLoader::loadAllFonts(bool exportToFile) void FontLoader::loadAllFonts(bool exportToFile)
{ {
/* const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups ();
for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it) std::string pattern = "Fonts/";
mVFS->normalizeFilename(pattern);
std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(pattern);
while (found != index.end())
{ {
Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "*.fnt"); const std::string& name = found->first;
for (Ogre::StringVector::iterator resource = resourcesInThisGroup->begin(); resource != resourcesInThisGroup->end(); ++resource) 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) 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; 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"); fail(file, fileName, "File too small to be a valid font");
int one; 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"); fail(file, fileName, "File too small to be a valid font");
if (one != 1) if (one != 1)
fail(file, fileName, "Unexpected value"); 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"); fail(file, fileName, "File too small to be a valid font");
if (one != 1) if (one != 1)
fail(file, fileName, "Unexpected value"); fail(file, fileName, "Unexpected value");
char name_[284]; 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"); fail(file, fileName, "File too small to be a valid font");
std::string name(name_); std::string name(name_);
GlyphInfo data[256]; 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"); fail(file, fileName, "File too small to be a valid font");
file->close();
file.reset();
// Create the font texture // Create the font texture
std::string bitmapFilename = "Fonts/" + std::string(name) + ".tex"; 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; int width, height;
if (bitmapFile->read(&width, sizeof(int)) < sizeof(int)) bitmapFile->read((char*)&width, sizeof(int));
fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap"); 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"); fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap");
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
fail(bitmapFile, bitmapFilename, "Width and height must be positive"); fail(bitmapFile, bitmapFilename, "Width and height must be positive");
std::vector<Ogre::uchar> textureData; std::vector<char> textureData;
textureData.resize(width*height*4); textureData.resize(width*height*4);
if (bitmapFile->read(&textureData[0], width*height*4) < (size_t)(width*height*4)) bitmapFile->read(&textureData[0], width*height*4);
fail(bitmapFile, bitmapFilename, "Bitmap does not contain the specified number of pixels"); if (!bitmapFile->good())
bitmapFile->close(); fail(bitmapFile, bitmapFilename, "File too small to be a valid bitmap");
bitmapFile.reset();
std::string resourceName; std::string resourceName;
if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic")) if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic"))
@ -239,24 +272,31 @@ namespace Gui
resourceName = "Century Gothic"; resourceName = "Century Gothic";
else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric")) else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric"))
resourceName = "Daedric"; resourceName = "Daedric";
else
return; // no point in loading it, since there is no way of using additional fonts
std::string textureName = name; std::string textureName = name;
Ogre::Image image;
image.loadDynamicImage(&textureData[0], width, height, Ogre::PF_BYTE_RGBA); osg::ref_ptr<osg::Image> image = new osg::Image;
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual(textureName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, unsigned char* bytes = (unsigned char*)calloc(width*height*4, sizeof(unsigned char));
Ogre::TEX_TYPE_2D, memcpy(bytes, &textureData[0], textureData.size());
width, height, 0, Ogre::PF_BYTE_RGBA); image->setImage(width, height, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, bytes, osg::Image::USE_MALLOC_FREE);
texture->loadImage(image);
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImage(image);
if (exportToFile) if (exportToFile)
image.save(resourceName + ".png"); {
std::cout << "Writing " << resourceName + ".png" << std::endl;
osgDB::writeImageFile(*image, resourceName + ".png");
}
// Register the font with MyGUI // Register the font with MyGUI
MyGUI::ResourceManualFont* font = static_cast<MyGUI::ResourceManualFont*>( MyGUI::ResourceManualFont* font = static_cast<MyGUI::ResourceManualFont*>(
MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont")); 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 // We need to emulate loading from XML because the data members are private as of mygui 3.2.0
MyGUI::xml::Document xmlDocument; MyGUI::xml::Document xmlDocument;
@ -390,6 +430,7 @@ namespace Gui
if (exportToFile) if (exportToFile)
{ {
std::cout << "Writing " << resourceName + ".xml" << std::endl;
xmlDocument.createDeclaration(); xmlDocument.createDeclaration();
xmlDocument.save(resourceName + ".xml"); xmlDocument.save(resourceName + ".xml");
} }

@ -1,26 +1,46 @@
#ifndef MWGUI_FONTLOADER_H #ifndef OPENMW_COMPONENTS_FONTLOADER_H
#define MWGUI_FONTLOADER_H #define OPENMW_COMPONENTS_FONTLOADER_H
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
namespace VFS
{
class Manager;
}
namespace MyGUI
{
class ITexture;
class ResourceManualFont;
}
namespace Gui 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 class FontLoader
{ {
public: 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? /// @param exportToFile export the converted fonts (Images and XML with glyph metrics) to files?
void loadAllFonts (bool exportToFile); void loadAllFonts (bool exportToFile);
private: private:
ToUTF8::FromType mEncoding; ToUTF8::FromType mEncoding;
const VFS::Manager* mVFS;
std::vector<MyGUI::ITexture*> mTextures;
std::vector<MyGUI::ResourceManualFont*> mFonts;
/// @param exportToFile export the converted font (Image and XML with glyph metrics) to files? /// @param exportToFile export the converted font (Image and XML with glyph metrics) to files?
void loadFont (const std::string& fileName, bool exportToFile); void loadFont (const std::string& fileName, bool exportToFile);
FontLoader(const FontLoader&);
void operator=(const FontLoader&);
}; };
} }

Loading…
Cancel
Save