From 18bece731a894f004357d38e5d692fb997b6c268 Mon Sep 17 00:00:00 2001 From: timoore Date: Fri, 6 Jun 2008 19:02:17 +0000 Subject: [PATCH] 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. --- src/Cockpit/hud.cxx | 1 + src/GUI/gui.cxx | 1 + src/GUI/new_gui.cxx | 124 +++++++++++++++++++++++++++++++++--------- src/GUI/new_gui.hxx | 43 ++++++++++++++- src/Main/renderer.cxx | 7 ++- 5 files changed, 145 insertions(+), 31 deletions(-) diff --git a/src/Cockpit/hud.cxx b/src/Cockpit/hud.cxx index 606a29efb..564b536dc 100644 --- a/src/Cockpit/hud.cxx +++ b/src/Cockpit/hud.cxx @@ -542,6 +542,7 @@ void fgTextList::draw() vector::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); diff --git a/src/GUI/gui.cxx b/src/GUI/gui.cxx index b730270f5..69b172d1b 100644 --- a/src/GUI/gui.cxx +++ b/src/GUI/gui.cxx @@ -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"), diff --git a/src/GUI/new_gui.cxx b/src/GUI/new_gui.cxx index 9f67a41d3..c6057b771 100644 --- a/src/GUI/new_gui.cxx +++ b/src/GUI/new_gui.cxx @@ -1,5 +1,9 @@ // new_gui.cxx: implementation of XML-configurable GUI support. +#include #include +#include +#include +#include #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 + { + 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::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(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 diff --git a/src/GUI/new_gui.hxx b/src/GUI/new_gui.hxx index 674bd73e2..3fb1703d2 100644 --- a/src/GUI/new_gui.hxx +++ b/src/GUI/new_gui.hxx @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -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 + { + 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 _fonts; - typedef map::const_iterator _itt_t; + typedef map TexFontMap; + typedef map 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(); }; diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 8840ca5bb..56b68cc08 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -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; } -- 2.39.5