]> git.mxchange.org Git - flightgear.git/blob - src/GUI/FGFontCache.cxx
Code cleanups, code updates and fix at least on (possible) devide-by-zero
[flightgear.git] / src / GUI / FGFontCache.cxx
1 //
2 //  This program is free software; you can redistribute it and/or
3 //  modify it under the terms of the GNU General Public License as
4 //  published by the Free Software Foundation; either version 2 of the
5 //  License, or (at your option) any later version.
6 // 
7 //  This program is distributed in the hope that it will be useful, but
8 //  WITHOUT ANY WARRANTY; without even the implied warranty of
9 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 //  General Public License for more details.
11 //
12 //  You should have received a copy of the GNU General Public License
13 //  along with this program; if not, write to the Free Software
14 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15 //
16 #ifdef HAVE_CONFIG_H
17 #  include <config.h>
18 #endif
19
20 #ifdef HAVE_WINDOWS_H
21 #include <windows.h>
22 #endif
23
24 #include "FGFontCache.hxx"
25
26 #include <plib/fnt.h>
27 #include <plib/pu.h>
28
29 #include <simgear/props/props.hxx>
30
31 #include <Main/globals.hxx>
32
33 ////////////////////////////////////////////////////////////////////////
34 // FGFontCache class.
35 ////////////////////////////////////////////////////////////////////////
36
37 static std::auto_ptr<FGFontCache> global_fontCacheInstance;
38
39
40 extern puFont FONT_HELVETICA_14;
41 extern puFont FONT_SANS_12B;
42 extern puFont FONT_HELVETICA_12;
43
44 namespace
45 {
46 struct GuiFont
47 {
48     const char* name;
49     puFont *font;
50     struct Predicate
51         : public std::unary_function<const GuiFont, bool>
52     {
53         Predicate(const std::string& name_) : name(name_) {}
54         bool operator() (const GuiFont& f1) const
55         {
56             return (name == f1.name);
57         }
58         const std::string name;
59     };
60 };
61
62 const GuiFont guifonts[] = {
63     { "default",      &PUFONT_HELVETICA_12 },
64     { "FIXED_8x13",   &PUFONT_8_BY_13 },
65     { "FIXED_9x15",   &PUFONT_9_BY_15 },
66     { "TIMES_10",     &PUFONT_TIMES_ROMAN_10 },
67     { "TIMES_24",     &PUFONT_TIMES_ROMAN_24 },
68     { "HELVETICA_10", &PUFONT_HELVETICA_10 },
69     { "HELVETICA_12", &FONT_HELVETICA_12 },
70     { "HELVETICA_14", &FONT_HELVETICA_14 },
71     { "HELVETICA_18", &PUFONT_HELVETICA_18 },
72     { "SANS_12B",     &FONT_SANS_12B },
73     { 0 }
74 };
75
76 const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])-1];
77 }
78
79 FGFontCache* FGFontCache::instance()
80 {
81     if (!global_fontCacheInstance.get()) {
82         global_fontCacheInstance.reset(new FGFontCache);
83     }
84
85     return global_fontCacheInstance.get();
86 }
87
88 FGFontCache::FGFontCache() :
89     _initialized(false)
90 {
91 }
92
93 FGFontCache::~FGFontCache()
94 {
95    PuFontMap::iterator it, end = _puFonts.end();
96    for (it = _puFonts.begin(); it != end; ++it)
97        delete it->second;
98 }
99
100 inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
101                                                    const FntParams& f2) const
102 {
103     int comp = f1.name.compare(f2.name);
104     if (comp < 0)
105         return true;
106     else if (comp > 0)
107         return false;
108     if (f1.size < f2.size)
109         return true;
110     else if (f1.size > f2.size)
111         return false;
112     return f1.slant < f2.slant;
113 }
114
115 struct FGFontCache::fnt *
116 FGFontCache::getfnt(const std::string& fontName, float size, float slant)
117 {
118     FntParams fntParams(fontName, size, slant);
119     PuFontMap::iterator i = _puFonts.find(fntParams);
120     if (i != _puFonts.end())
121         return i->second;
122     // fntTexFont s are all preloaded into the _texFonts map
123     TexFontMap::iterator texi = _texFonts.find(fontName);
124     fntTexFont* texfont = 0;
125     puFont* pufont = 0;
126     if (texi != _texFonts.end()) {
127         texfont = texi->second;
128     } else {
129         const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
130                                               GuiFont::Predicate(fontName));
131         if (guifont != guifontsEnd) {
132             pufont = guifont->font;
133         }
134     }
135     fnt* f = new fnt;
136     if (pufont) {
137         f->pufont = pufont;
138     } else if (texfont) {
139         f->texfont = texfont;
140         f->pufont = new puFont;
141         f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
142     } else {
143         f->pufont = guifonts[0].font;
144     }
145     _puFonts[fntParams] = f;
146     return f;
147 }
148
149 puFont *
150 FGFontCache::get(const std::string& name, float size, float slant)
151 {
152     return getfnt(name, size, slant)->pufont;
153 }
154
155 fntTexFont *
156 FGFontCache::getTexFont(const std::string& name, float size, float slant)
157 {
158     init();
159     return getfnt(name, size, slant)->texfont;
160 }
161
162 puFont *
163 FGFontCache::get(SGPropertyNode *node)
164 {
165     if (!node)
166         return get("Helvetica.txf", 15.0, 0.0);
167
168     const char *name = node->getStringValue("name", "Helvetica.txf");
169     float size = node->getFloatValue("size", 15.0);
170     float slant = node->getFloatValue("slant", 0.0);
171
172     return get(name, size, slant);
173 }
174
175 void FGFontCache::init()
176 {
177     if (!_initialized) {
178         char *envp = ::getenv("FG_FONTS");
179         if (envp != NULL) {
180             _path.set(envp);
181         } else {
182             _path.set(globals->get_fg_root());
183             _path.append("Fonts");
184         }
185         _initialized = true;
186     }
187 }
188
189 SGPath
190 FGFontCache::getfntpath(const std::string& name)
191 {
192     init();
193     SGPath path(_path);
194     if (name != "") {
195         path.append(name);
196         if (path.exists())
197             return path;
198     }
199
200     path = SGPath(_path);
201     path.append("Helvetica.txf");
202     
203     return path;
204 }
205
206 bool FGFontCache::initializeFonts()
207 {
208     static std::string fontext("txf");
209     init();
210     ulDir* fontdir = ulOpenDir(_path.c_str());
211     if (!fontdir)
212         return false;
213     const ulDirEnt *dirEntry;
214     while ((dirEntry = ulReadDir(fontdir)) != 0) {
215         SGPath path(_path);
216         path.append(dirEntry->d_name);
217         if (path.extension() == fontext) {
218             fntTexFont* f = new fntTexFont;
219             if (f->load((char *)path.c_str()))
220                 _texFonts[std::string(dirEntry->d_name)] = f;
221             else
222                 delete f;
223         }
224     }
225     ulCloseDir(fontdir);
226     return true;
227 }
228
229 FGFontCache::fnt::~fnt()
230 {
231     if (texfont) { 
232         delete pufont; 
233         delete texfont;
234     }
235 }
236