1
0
Fork 0

Fix GUI and HUD text rendering problems.

After the changes that moved the GUI and HUD to a slave camera, the
texture-based fonts wouldn't display. The main fixes here are making
sure that the TXF textures are all loaded into the font cache early,
and explicitly setting the active texture unit in the GUI / HUD
drawImplementation.
This commit is contained in:
timoore 2008-06-06 19:02:17 +00:00
parent b27f73f4f4
commit 18bece731a
5 changed files with 145 additions and 31 deletions

View file

@ -542,6 +542,7 @@ void fgTextList::draw()
vector<fgText>::iterator lastString = List.end();
glPushAttrib(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
if (HUDprop->isTransparent())
glBlendFunc(GL_SRC_ALPHA, GL_ONE);

View file

@ -80,6 +80,7 @@ public:
puSetDefaultColourScheme (0.8, 0.8, 0.9, 1);
FGFontCache *fc = globals->get_fontcache();
fc->initializeFonts();
puFont *GuiFont
= fc->get(globals->get_locale()->getStringValue("font",
"typewriter.txf"),

View file

@ -1,5 +1,9 @@
// new_gui.cxx: implementation of XML-configurable GUI support.
#include <algorithm>
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <dirent.h>
#include "new_gui.hxx"
@ -13,7 +17,6 @@
#include "menubar.hxx"
#include "dialog.hxx"
#include "SafeTexFont.hxx"
extern puFont FONT_HELVETICA_14;
extern puFont FONT_SANS_12B;
@ -400,10 +403,25 @@ FGColor::merge(const FGColor *color)
// FGFontCache class.
////////////////////////////////////////////////////////////////////////
static const struct {
namespace
{
struct GuiFont
{
const char *name;
puFont *font;
} guifonts[] = {
struct Predicate
: public std::unary_function<const GuiFont, bool>
{
Predicate(const char* name_) : name(name_) {}
bool operator() (const GuiFont& f1) const
{
return std::strcmp(f1.name, name) == 0;
}
const char* name;
};
};
const GuiFont guifonts[] = {
{ "default", &FONT_HELVETICA_14 },
{ "FIXED_8x13", &PUFONT_8_BY_13 },
{ "FIXED_9x15", &PUFONT_9_BY_15 },
@ -413,10 +431,11 @@ static const struct {
{ "HELVETICA_12", &PUFONT_HELVETICA_12 },
{ "HELVETICA_14", &FONT_HELVETICA_14 },
{ "HELVETICA_18", &PUFONT_HELVETICA_18 },
{ "SANS_12B", &FONT_SANS_12B },
{ 0, 0 }
{ "SANS_12B", &FONT_SANS_12B }
};
const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])];
}
FGFontCache::FGFontCache() :
_initialized(false)
@ -425,31 +444,59 @@ FGFontCache::FGFontCache() :
FGFontCache::~FGFontCache()
{
map<const string, fnt *>::iterator it, end = _fonts.end();
for (it = _fonts.begin(); it != end; ++it)
PuFontMap::iterator it, end = _puFonts.end();
for (it = _puFonts.begin(); it != end; ++it)
delete it->second;
}
inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
const FntParams& f2) const
{
int comp = f1.name.compare(f2.name);
if (comp < 0)
return true;
else if (comp > 0)
return false;
if (f1.size < f2.size)
return true;
else if (f1.size > f2.size)
return false;
return f1.slant < f2.slant;
}
struct FGFontCache::fnt *
FGFontCache::getfnt(const char *name, float size, float slant)
{
_itt_t it;
if ((it = _fonts.find(name)) != _fonts.end())
return it->second;
SGPath path = getfntpath(name);
fnt *f = new fnt();
f->texfont = new flightgear::SafeTexFont;
if (f->texfont->load((char *)path.c_str())) {
string fontName(name);
FntParams fntParams(fontName, size, slant);
PuFontMap::iterator i = _puFonts.find(fntParams);
if (i != _puFonts.end())
return i->second;
// fntTexFont s are all preloaded into the _texFonts map
TexFontMap::iterator texi = _texFonts.find(fontName);
fntTexFont* texfont = 0;
puFont* pufont = 0;
if (texi != _texFonts.end()) {
texfont = texi->second;
} else {
const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
GuiFont::Predicate(name));
if (guifont != guifontsEnd) {
pufont = guifont->font;
}
}
fnt* f = new fnt;
if (pufont) {
f->pufont = pufont;
} else if (texfont) {
f->texfont = texfont;
f->pufont = new puFont;
f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
return _fonts[name] = f;
} else {
f->pufont = guifonts[0].font;
}
delete f;
return _fonts["default"];
_puFonts[fntParams] = f;
return f;
}
puFont *
@ -477,8 +524,7 @@ FGFontCache::get(SGPropertyNode *node)
return get(name, size, slant);
}
SGPath
FGFontCache::getfntpath(const char *name)
void FGFontCache::init()
{
if (!_initialized) {
char *envp = ::getenv("FG_FONTS");
@ -488,13 +534,14 @@ FGFontCache::getfntpath(const char *name)
_path.set(globals->get_fg_root());
_path.append("Fonts");
}
for (int i = 0; guifonts[i].name; i++)
_fonts[guifonts[i].name] = new fnt(guifonts[i].font);
_initialized = true;
}
}
SGPath
FGFontCache::getfntpath(const char *name)
{
init();
SGPath path(_path);
if (name && std::string(name) != "") {
path.append(name);
@ -508,4 +555,27 @@ FGFontCache::getfntpath(const char *name)
return path;
}
bool FGFontCache::initializeFonts()
{
static string fontext("txf");
init();
DIR* fontdir = opendir(_path.c_str());
if (!fontdir)
return false;
const dirent *dirEntry;
while ((dirEntry = readdir(fontdir)) != 0) {
SGPath path(_path);
path.append(dirEntry->d_name);
if (path.extension() == fontext) {
fntTexFont* f = new fntTexFont;
if (f->load((char *)path.c_str()))
_texFonts[string(dirEntry->d_name)] = f;
else
delete f;
}
}
closedir(fontdir);
return true;
}
// end of new_gui.cxx

View file

@ -18,6 +18,7 @@
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/misc/sg_path.hxx>
#include <functional>
#include <vector>
#include <map>
@ -286,23 +287,51 @@ private:
/**
* A small class to keep all fonts available for future use.
* A class to keep all fonts available for future use.
* This also assures a font isn't resident more than once.
*/
class FGFontCache {
private:
// The parameters of a request to the cache.
struct FntParams
{
const std::string name;
const float size;
const float slant;
FntParams() : size(0.0f), slant(0.0f) {}
FntParams(const FntParams& rhs)
: name(rhs.name), size(rhs.size), slant(rhs.slant)
{
}
FntParams(const std::string& name_, float size_, float slant_)
: name(name_), size(size_), slant(slant_)
{
}
};
struct FntParamsLess
: public std::binary_function<const FntParams, const FntParams, bool>
{
bool operator() (const FntParams& f1, const FntParams& f2) const;
};
struct fnt {
fnt(puFont *pu = 0) : pufont(pu), texfont(0) {}
~fnt() { if (texfont) { delete pufont; delete texfont; } }
// Font used by plib GUI code
puFont *pufont;
// TXF font
fntTexFont *texfont;
};
// Path to the font directory
SGPath _path;
map<const string,fnt *> _fonts;
typedef map<const string,fnt *>::const_iterator _itt_t;
typedef map<const string, fntTexFont*> TexFontMap;
typedef map<const FntParams, fnt*, FntParamsLess> PuFontMap;
TexFontMap _texFonts;
PuFontMap _puFonts;
bool _initialized;
struct fnt *getfnt(const char *name, float size, float slant);
void init();
public:
FGFontCache();
@ -314,6 +343,14 @@ public:
fntTexFont *getTexFont(const char *name, float size=15.0, float slant=0.0);
SGPath getfntpath(const char *name);
/**
* Preload all the fonts in the FlightGear font directory. It is
* important to load the font textures early, with the proper
* graphics context current, so that no plib (or our own) code
* tries to load a font from disk when there's no current graphics
* context.
*/
bool initializeFonts();
};

View file

@ -159,6 +159,9 @@ public:
{
if (!fgOSIsMainContext(state.getGraphicsContext()))
return;
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
state.disableAllVertexArrays();
glPushAttrib(GL_ALL_ATTRIB_BITS);
@ -201,7 +204,8 @@ public:
{
if (!fgOSIsMainContext(state.getGraphicsContext()))
return;
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
state.disableAllVertexArrays();
glPushAttrib(GL_ALL_ATTRIB_BITS);
@ -222,6 +226,7 @@ public:
glPopClientAttrib();
glPopAttrib();
}
virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }