2011-11-19 20:25:51 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
//
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_WINDOWS_H
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "FGFontCache.hxx"
|
|
|
|
|
|
|
|
#include <plib/fnt.h>
|
|
|
|
#include <plib/pu.h>
|
|
|
|
|
|
|
|
#include <simgear/props/props.hxx>
|
|
|
|
|
|
|
|
#include <Main/globals.hxx>
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// FGFontCache class.
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2016-01-01 20:33:17 +00:00
|
|
|
static std::auto_ptr<FGFontCache> global_fontCacheInstance;
|
|
|
|
|
|
|
|
|
2011-11-19 20:25:51 +00:00
|
|
|
extern puFont FONT_HELVETICA_14;
|
|
|
|
extern puFont FONT_SANS_12B;
|
2012-04-21 14:25:53 +00:00
|
|
|
extern puFont FONT_HELVETICA_12;
|
2011-11-19 20:25:51 +00:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
struct GuiFont
|
|
|
|
{
|
2016-01-01 20:33:17 +00:00
|
|
|
const char* name;
|
2011-11-19 20:25:51 +00:00
|
|
|
puFont *font;
|
|
|
|
struct Predicate
|
|
|
|
: public std::unary_function<const GuiFont, bool>
|
|
|
|
{
|
2016-01-01 20:33:17 +00:00
|
|
|
Predicate(const std::string& name_) : name(name_) {}
|
2011-11-19 20:25:51 +00:00
|
|
|
bool operator() (const GuiFont& f1) const
|
|
|
|
{
|
2016-01-01 20:33:17 +00:00
|
|
|
return (name == f1.name);
|
2011-11-19 20:25:51 +00:00
|
|
|
}
|
2016-01-01 20:33:17 +00:00
|
|
|
const std::string name;
|
2011-11-19 20:25:51 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const GuiFont guifonts[] = {
|
|
|
|
{ "default", &PUFONT_HELVETICA_12 },
|
|
|
|
{ "FIXED_8x13", &PUFONT_8_BY_13 },
|
|
|
|
{ "FIXED_9x15", &PUFONT_9_BY_15 },
|
|
|
|
{ "TIMES_10", &PUFONT_TIMES_ROMAN_10 },
|
|
|
|
{ "TIMES_24", &PUFONT_TIMES_ROMAN_24 },
|
|
|
|
{ "HELVETICA_10", &PUFONT_HELVETICA_10 },
|
2012-04-21 14:25:53 +00:00
|
|
|
{ "HELVETICA_12", &FONT_HELVETICA_12 },
|
2011-11-19 20:25:51 +00:00
|
|
|
{ "HELVETICA_14", &FONT_HELVETICA_14 },
|
|
|
|
{ "HELVETICA_18", &PUFONT_HELVETICA_18 },
|
2012-07-06 06:28:45 +00:00
|
|
|
{ "SANS_12B", &FONT_SANS_12B },
|
|
|
|
{ 0 }
|
2011-11-19 20:25:51 +00:00
|
|
|
};
|
|
|
|
|
2012-07-06 06:28:45 +00:00
|
|
|
const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])-1];
|
2011-11-19 20:25:51 +00:00
|
|
|
}
|
|
|
|
|
2016-01-01 20:33:17 +00:00
|
|
|
FGFontCache* FGFontCache::instance()
|
|
|
|
{
|
|
|
|
if (!global_fontCacheInstance.get()) {
|
|
|
|
global_fontCacheInstance.reset(new FGFontCache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return global_fontCacheInstance.get();
|
|
|
|
}
|
|
|
|
|
2011-11-19 20:25:51 +00:00
|
|
|
FGFontCache::FGFontCache() :
|
|
|
|
_initialized(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FGFontCache::~FGFontCache()
|
|
|
|
{
|
|
|
|
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 *
|
2016-01-01 20:33:17 +00:00
|
|
|
FGFontCache::getfnt(const std::string& fontName, float size, float slant)
|
2011-11-19 20:25:51 +00:00
|
|
|
{
|
|
|
|
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,
|
2016-01-01 20:33:17 +00:00
|
|
|
GuiFont::Predicate(fontName));
|
2011-11-19 20:25:51 +00:00
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
f->pufont = guifonts[0].font;
|
|
|
|
}
|
|
|
|
_puFonts[fntParams] = f;
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
puFont *
|
2016-01-01 20:33:17 +00:00
|
|
|
FGFontCache::get(const std::string& name, float size, float slant)
|
2011-11-19 20:25:51 +00:00
|
|
|
{
|
|
|
|
return getfnt(name, size, slant)->pufont;
|
|
|
|
}
|
|
|
|
|
|
|
|
fntTexFont *
|
2016-01-01 20:33:17 +00:00
|
|
|
FGFontCache::getTexFont(const std::string& name, float size, float slant)
|
2011-11-19 20:25:51 +00:00
|
|
|
{
|
|
|
|
init();
|
|
|
|
return getfnt(name, size, slant)->texfont;
|
|
|
|
}
|
|
|
|
|
|
|
|
puFont *
|
|
|
|
FGFontCache::get(SGPropertyNode *node)
|
|
|
|
{
|
|
|
|
if (!node)
|
|
|
|
return get("Helvetica.txf", 15.0, 0.0);
|
|
|
|
|
|
|
|
const char *name = node->getStringValue("name", "Helvetica.txf");
|
|
|
|
float size = node->getFloatValue("size", 15.0);
|
|
|
|
float slant = node->getFloatValue("slant", 0.0);
|
|
|
|
|
|
|
|
return get(name, size, slant);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FGFontCache::init()
|
|
|
|
{
|
|
|
|
if (!_initialized) {
|
|
|
|
char *envp = ::getenv("FG_FONTS");
|
|
|
|
if (envp != NULL) {
|
|
|
|
_path.set(envp);
|
|
|
|
} else {
|
|
|
|
_path.set(globals->get_fg_root());
|
|
|
|
_path.append("Fonts");
|
|
|
|
}
|
|
|
|
_initialized = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPath
|
2016-01-01 20:33:17 +00:00
|
|
|
FGFontCache::getfntpath(const std::string& name)
|
2011-11-19 20:25:51 +00:00
|
|
|
{
|
|
|
|
init();
|
|
|
|
SGPath path(_path);
|
2016-01-01 20:33:17 +00:00
|
|
|
if (name != "") {
|
2011-11-19 20:25:51 +00:00
|
|
|
path.append(name);
|
|
|
|
if (path.exists())
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
path = SGPath(_path);
|
|
|
|
path.append("Helvetica.txf");
|
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FGFontCache::initializeFonts()
|
|
|
|
{
|
|
|
|
static std::string fontext("txf");
|
|
|
|
init();
|
|
|
|
ulDir* fontdir = ulOpenDir(_path.c_str());
|
|
|
|
if (!fontdir)
|
|
|
|
return false;
|
|
|
|
const ulDirEnt *dirEntry;
|
|
|
|
while ((dirEntry = ulReadDir(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[std::string(dirEntry->d_name)] = f;
|
|
|
|
else
|
|
|
|
delete f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ulCloseDir(fontdir);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
FGFontCache::fnt::~fnt()
|
|
|
|
{
|
|
|
|
if (texfont) {
|
|
|
|
delete pufont;
|
|
|
|
delete texfont;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|