00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "fontPool.h"
00016 #include "staticTextFont.h"
00017 #include "dynamicTextFont.h"
00018 #include "config_util.h"
00019 #include "config_express.h"
00020 #include "virtualFileSystem.h"
00021 #include "nodePath.h"
00022 #include "loader.h"
00023 #include "lightMutexHolder.h"
00024
00025 FontPool *FontPool::_global_ptr = (FontPool *)NULL;
00026
00027
00028
00029
00030
00031
00032
00033 void FontPool::
00034 write(ostream &out) {
00035 get_ptr()->ns_list_contents(out);
00036 }
00037
00038
00039
00040
00041
00042
00043 bool FontPool::
00044 ns_has_font(const string &str) {
00045 LightMutexHolder holder(_lock);
00046
00047 string index_str;
00048 Filename filename;
00049 int face_index;
00050 lookup_filename(str, index_str, filename, face_index);
00051
00052 Fonts::const_iterator ti;
00053 ti = _fonts.find(index_str);
00054 if (ti != _fonts.end()) {
00055
00056 return true;
00057 }
00058
00059 return false;
00060 }
00061
00062
00063
00064
00065
00066
00067 TextFont *FontPool::
00068 ns_load_font(const string &str) {
00069 string index_str;
00070 Filename filename;
00071 int face_index;
00072 lookup_filename(str, index_str, filename, face_index);
00073
00074 {
00075 LightMutexHolder holder(_lock);
00076
00077 Fonts::const_iterator ti;
00078 ti = _fonts.find(index_str);
00079 if (ti != _fonts.end()) {
00080
00081 return (*ti).second;
00082 }
00083 }
00084
00085 text_cat.info()
00086 << "Loading font " << filename << "\n";
00087
00088
00089
00090
00091 PT(TextFont) font;
00092
00093 string extension = filename.get_extension();
00094 if (extension.empty() || extension == "egg" || extension == "bam") {
00095 Loader *model_loader = Loader::get_global_ptr();
00096 PT(PandaNode) node = model_loader->load_sync(filename);
00097 if (node != (PandaNode *)NULL) {
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 font = new StaticTextFont(node);
00111 }
00112 }
00113
00114 #ifdef HAVE_FREETYPE
00115 if (font == (TextFont *)NULL || !font->is_valid()) {
00116
00117
00118 font = new DynamicTextFont(filename, face_index);
00119 }
00120 #endif
00121
00122 if (font == (TextFont *)NULL || !font->is_valid()) {
00123
00124 return NULL;
00125 }
00126
00127
00128 {
00129 LightMutexHolder holder(_lock);
00130
00131
00132 Fonts::const_iterator ti;
00133 ti = _fonts.find(index_str);
00134 if (ti != _fonts.end()) {
00135
00136 return (*ti).second;
00137 }
00138
00139 _fonts[index_str] = font;
00140 }
00141
00142 return font;
00143 }
00144
00145
00146
00147
00148
00149
00150 void FontPool::
00151 ns_add_font(const string &str, TextFont *font) {
00152 LightMutexHolder holder(_lock);
00153
00154 string index_str;
00155 Filename filename;
00156 int face_index;
00157 lookup_filename(str, index_str, filename, face_index);
00158
00159
00160 _fonts[index_str] = font;
00161 }
00162
00163
00164
00165
00166
00167
00168 void FontPool::
00169 ns_release_font(const string &str) {
00170 LightMutexHolder holder(_lock);
00171
00172 string index_str;
00173 Filename filename;
00174 int face_index;
00175 lookup_filename(str, index_str, filename, face_index);
00176
00177 Fonts::iterator ti;
00178 ti = _fonts.find(index_str);
00179 if (ti != _fonts.end()) {
00180 _fonts.erase(ti);
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189 void FontPool::
00190 ns_release_all_fonts() {
00191 LightMutexHolder holder(_lock);
00192
00193 _fonts.clear();
00194 }
00195
00196
00197
00198
00199
00200
00201 int FontPool::
00202 ns_garbage_collect() {
00203 LightMutexHolder holder(_lock);
00204
00205 int num_released = 0;
00206 Fonts new_set;
00207
00208 Fonts::iterator ti;
00209 for (ti = _fonts.begin(); ti != _fonts.end(); ++ti) {
00210 TextFont *font = (*ti).second;
00211 if (font->get_ref_count() == 1) {
00212 if (text_cat.is_debug()) {
00213 text_cat.debug()
00214 << "Releasing " << (*ti).first << "\n";
00215 }
00216 num_released++;
00217 } else {
00218 new_set.insert(new_set.end(), *ti);
00219 }
00220 }
00221
00222 _fonts.swap(new_set);
00223 return num_released;
00224 }
00225
00226
00227
00228
00229
00230
00231 void FontPool::
00232 ns_list_contents(ostream &out) const {
00233 LightMutexHolder holder(_lock);
00234
00235 out << _fonts.size() << " fonts:\n";
00236 Fonts::const_iterator ti;
00237 for (ti = _fonts.begin(); ti != _fonts.end(); ++ti) {
00238 TextFont *font = (*ti).second;
00239 out << " " << (*ti).first
00240 << " (count = " << font->get_ref_count() << ")\n";
00241 }
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 void FontPool::
00258 lookup_filename(const string &str, string &index_str,
00259 Filename &filename, int &face_index) {
00260 int colon = (int)str.length() - 1;
00261
00262 while (colon >= 0 && isdigit(str[colon])) {
00263 --colon;
00264 }
00265 if (colon >= 0 && str[colon] == ':') {
00266 string digits = str.substr(colon + 1);
00267 filename = str.substr(0, colon);
00268 face_index = atoi(digits.c_str());
00269 } else {
00270 filename = str;
00271 face_index = 0;
00272 }
00273
00274
00275 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00276 vfs->resolve_filename(filename, get_model_path());
00277
00278 ostringstream strm;
00279 strm << filename << ":" << face_index;
00280 index_str = strm.str();
00281 }
00282
00283
00284
00285
00286
00287
00288
00289 FontPool *FontPool::
00290 get_ptr() {
00291 if (_global_ptr == (FontPool *)NULL) {
00292 _global_ptr = new FontPool;
00293 }
00294 return _global_ptr;
00295 }