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