]> git.mxchange.org Git - flightgear.git/blob - utils/fgpanel/FGFontCache.cxx
Simplify logic now SGPath::desktop works on Windows.
[flightgear.git] / utils / fgpanel / 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 #include "FGGLApplication.hxx"
21 #ifdef HAVE_WINDOWS_H
22 #include <windows.h>
23 #endif
24
25 #include <map>
26 #include <algorithm>
27
28 #include <plib/fnt.h>
29 #include <plib/pu.h>
30
31 #include "ApplicationProperties.hxx"
32 #include "FGFontCache.hxx"
33
34
35 ////////////////////////////////////////////////////////////////////////
36 // FGFontCache class.
37 ////////////////////////////////////////////////////////////////////////
38
39 //extern puFont FONT_HELVETICA_14;
40 //extern puFont FONT_SANS_12B;
41
42 namespace
43 {
44 struct GuiFont
45 {
46     const char *name;
47     puFont *font;
48     struct Predicate
49         : public std::unary_function<const GuiFont, bool>
50     {
51         Predicate(const char* name_) : name(name_) {}
52         bool operator() (const GuiFont& f1) const
53         {
54             return ::strcmp(f1.name, name) == 0;
55         }
56         const char* name;
57     };
58 };
59
60 const GuiFont guifonts[] = {
61     { "default",      &PUFONT_HELVETICA_12 },
62     { "FIXED_8x13",   &PUFONT_8_BY_13 },
63     { "FIXED_9x15",   &PUFONT_9_BY_15 },
64     { "TIMES_10",     &PUFONT_TIMES_ROMAN_10 },
65     { "TIMES_24",     &PUFONT_TIMES_ROMAN_24 },
66     { "HELVETICA_10", &PUFONT_HELVETICA_10 },
67     { "HELVETICA_12", &PUFONT_HELVETICA_12 },
68 //    { "HELVETICA_14", &FONT_HELVETICA_14 },
69     { "HELVETICA_18", &PUFONT_HELVETICA_18 },
70 //    { "SANS_12B",     &FONT_SANS_12B },
71     { 0 }
72 };
73
74 const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])-1];
75 }
76
77 FGFontCache::fnt::~fnt()
78 {
79     if (texfont) { 
80         delete pufont; 
81         delete texfont;
82     }
83 }
84
85 FGFontCache::FGFontCache() :
86     _initialized(false)
87 {
88 }
89
90 FGFontCache::~FGFontCache()
91 {
92    PuFontMap::iterator it, end = _puFonts.end();
93    for (it = _puFonts.begin(); it != end; ++it)
94        delete it->second;
95 }
96
97 inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
98                                                    const FntParams& f2) const
99 {
100     int comp = f1.name.compare(f2.name);
101     if (comp < 0)
102         return true;
103     else if (comp > 0)
104         return false;
105     if (f1.size < f2.size)
106         return true;
107     else if (f1.size > f2.size)
108         return false;
109     return f1.slant < f2.slant;
110 }
111
112 struct FGFontCache::fnt *
113 FGFontCache::getfnt(const char *name, float size, float slant)
114 {
115     std::string fontName(name);
116     FntParams fntParams(fontName, size, slant);
117     PuFontMap::iterator i = _puFonts.find(fntParams);
118     if (i != _puFonts.end())
119         return i->second;
120     // fntTexFont s are all preloaded into the _texFonts map
121     TexFontMap::iterator texi = _texFonts.find(fontName);
122     fntTexFont* texfont = 0;
123     puFont* pufont = 0;
124     if (texi != _texFonts.end()) {
125         texfont = texi->second;
126     } else {
127         const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
128                                               GuiFont::Predicate(name));
129         if (guifont != guifontsEnd) {
130             pufont = guifont->font;
131         }
132     }
133     fnt* f = new fnt;
134     if (pufont) {
135         f->pufont = pufont;
136     } else if (texfont) {
137         f->texfont = texfont;
138         f->pufont = new puFont;
139         f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
140     } else {
141         f->pufont = guifonts[0].font;
142     }
143     _puFonts[fntParams] = f;
144     return f;
145 }
146
147 puFont *
148 FGFontCache::get(const char *name, float size, float slant)
149 {
150     return getfnt(name, size, slant)->pufont;
151 }
152
153 fntTexFont *
154 FGFontCache::getTexFont(const char *name, float size, float slant)
155 {
156     init();
157     return getfnt(name, size, slant)->texfont;
158 }
159
160 puFont *
161 FGFontCache::get(SGPropertyNode *node)
162 {
163     if (!node)
164         return get("Helvetica.txf", 15.0, 0.0);
165
166     const char *name = node->getStringValue("name", "Helvetica.txf");
167     float size = node->getFloatValue("size", 15.0);
168     float slant = node->getFloatValue("slant", 0.0);
169
170     return get(name, size, slant);
171 }
172
173 void FGFontCache::init()
174 {
175     if (!_initialized) {
176         char *envp = ::getenv("FG_FONTS");
177         if (envp != NULL) {
178             _path.set(envp);
179         } else {
180             _path.set(ApplicationProperties::GetRootPath("Fonts").str());
181         }
182         _initialized = true;
183     }
184 }
185
186 SGPath
187 FGFontCache::getfntpath(const char *name)
188 {
189     init();
190     SGPath path(_path);
191     if (name && std::string(name) != "") {
192         path.append(name);
193         if (path.exists())
194             return path;
195     }
196
197     path = SGPath(_path);
198     path.append("Helvetica.txf");
199     
200     return path;
201 }
202
203 bool FGFontCache::initializeFonts()
204 {
205     static std::string fontext("txf");
206     init();
207     ulDir* fontdir = ulOpenDir(_path.c_str());
208     if (!fontdir)
209         return false;
210     const ulDirEnt *dirEntry;
211     while ((dirEntry = ulReadDir(fontdir)) != 0) {
212         SGPath path(_path);
213         path.append(dirEntry->d_name);
214         if (path.extension() == fontext) {
215             fntTexFont* f = new fntTexFont;
216             if (f->load((char *)path.c_str()))
217                 _texFonts[std::string(dirEntry->d_name)] = f;
218             else
219                 delete f;
220         }
221     }
222     ulCloseDir(fontdir);
223     return true;
224 }
225
226 // end of new_gui.cxx
227