Panda3D
fontPool.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file fontPool.cxx
10  * @author drose
11  * @date 2003-01-31
12  */
13 
14 #include "fontPool.h"
15 #include "staticTextFont.h"
16 #include "dynamicTextFont.h"
17 #include "config_putil.h"
18 #include "config_express.h"
19 #include "virtualFileSystem.h"
20 #include "nodePath.h"
21 #include "loader.h"
22 #include "lightMutexHolder.h"
23 
24 using std::string;
25 
26 FontPool *FontPool::_global_ptr = nullptr;
27 
28 /**
29  * Lists the contents of the font pool to the indicated output stream.
30  */
32 write(std::ostream &out) {
33  get_ptr()->ns_list_contents(out);
34 }
35 
36 /**
37  * The nonstatic implementation of has_font().
38  */
39 bool FontPool::
40 ns_has_font(const string &str) {
41  LightMutexHolder holder(_lock);
42 
43  string index_str;
44  Filename filename;
45  int face_index;
46  lookup_filename(str, index_str, filename, face_index);
47 
48  Fonts::const_iterator ti;
49  ti = _fonts.find(index_str);
50  if (ti != _fonts.end()) {
51  // This font was previously loaded.
52  return true;
53  }
54 
55  return false;
56 }
57 
58 /**
59  * The nonstatic implementation of load_font().
60  */
61 TextFont *FontPool::
62 ns_load_font(const string &str) {
63  string index_str;
64  Filename filename;
65  int face_index;
66  lookup_filename(str, index_str, filename, face_index);
67 
68  {
69  LightMutexHolder holder(_lock);
70 
71  Fonts::const_iterator ti;
72  ti = _fonts.find(index_str);
73  if (ti != _fonts.end()) {
74  // This font was previously loaded.
75  return (*ti).second;
76  }
77  }
78 
79  text_cat.info()
80  << "Loading font " << filename << "\n";
81 
82  // Now, figure out how to load the font. If its filename extension is "egg"
83  // or "bam", or if it's unspecified, assume it's a model file, representing
84  // a static font.
85  PT(TextFont) font;
86 
87  string extension = filename.get_extension();
88  if (extension.empty() || extension == "egg" || extension == "bam") {
89  Loader *model_loader = Loader::get_global_ptr();
90  PT(PandaNode) node = model_loader->load_sync(filename);
91  if (node != nullptr) {
92  // It is a model. Elevate all the priorities by 1, and make a font out
93  // of it.
94 
95  // On second thought, why should we elevate the priorities? The
96  // DynamicTextFont doesn't do this, and doing so for the StaticTextFont
97  // only causes problems (it changes the default ColorAttrib from pri -1
98  // to pri 0).
99  /*
100  NodePath np(node);
101  np.adjust_all_priorities(1);
102  */
103 
104  font = new StaticTextFont(node);
105  }
106  }
107 
108 #ifdef HAVE_FREETYPE
109  if (font == nullptr || !font->is_valid()) {
110  // If we couldn't load the font as a model, try using FreeType to load it
111  // as a font file.
112  font = new DynamicTextFont(filename, face_index);
113  }
114 #endif
115 
116  if (font == nullptr || !font->is_valid()) {
117  // This font was not found or could not be read.
118  return nullptr;
119  }
120 
121 
122  {
123  LightMutexHolder holder(_lock);
124 
125  // Look again. It may have been loaded by another thread.
126  Fonts::const_iterator ti;
127  ti = _fonts.find(index_str);
128  if (ti != _fonts.end()) {
129  // This font was previously loaded.
130  return (*ti).second;
131  }
132 
133  _fonts[index_str] = font;
134  }
135 
136  return font;
137 }
138 
139 /**
140  * The nonstatic implementation of add_font().
141  */
142 void FontPool::
143 ns_add_font(const string &str, TextFont *font) {
144  LightMutexHolder holder(_lock);
145 
146  string index_str;
147  Filename filename;
148  int face_index;
149  lookup_filename(str, index_str, filename, face_index);
150 
151  // We blow away whatever font was there previously, if any.
152  _fonts[index_str] = font;
153 }
154 
155 /**
156  * The nonstatic implementation of release_font().
157  */
158 void FontPool::
159 ns_release_font(const string &str) {
160  LightMutexHolder holder(_lock);
161 
162  string index_str;
163  Filename filename;
164  int face_index;
165  lookup_filename(str, index_str, filename, face_index);
166 
167  Fonts::iterator ti;
168  ti = _fonts.find(index_str);
169  if (ti != _fonts.end()) {
170  _fonts.erase(ti);
171  }
172 }
173 
174 /**
175  * The nonstatic implementation of release_all_fonts().
176  */
177 void FontPool::
178 ns_release_all_fonts() {
179  LightMutexHolder holder(_lock);
180 
181  _fonts.clear();
182 }
183 
184 /**
185  * The nonstatic implementation of garbage_collect().
186  */
187 int FontPool::
188 ns_garbage_collect() {
189  LightMutexHolder holder(_lock);
190 
191  int num_released = 0;
192  Fonts new_set;
193 
194  Fonts::iterator ti;
195  for (ti = _fonts.begin(); ti != _fonts.end(); ++ti) {
196  TextFont *font = (*ti).second;
197  if (font->get_ref_count() == 1) {
198  if (text_cat.is_debug()) {
199  text_cat.debug()
200  << "Releasing " << (*ti).first << "\n";
201  }
202  num_released++;
203  } else {
204  new_set.insert(new_set.end(), *ti);
205  }
206  }
207 
208  _fonts.swap(new_set);
209  return num_released;
210 }
211 
212 /**
213  * The nonstatic implementation of list_contents().
214  */
215 void FontPool::
216 ns_list_contents(std::ostream &out) const {
217  LightMutexHolder holder(_lock);
218 
219  out << _fonts.size() << " fonts:\n";
220  Fonts::const_iterator ti;
221  for (ti = _fonts.begin(); ti != _fonts.end(); ++ti) {
222  TextFont *font = (*ti).second;
223  out << " " << (*ti).first
224  << " (count = " << font->get_ref_count() << ")\n";
225  }
226 }
227 
228 /**
229  * Accepts a font "filename", which might consist of a filename followed by an
230  * optional colon and a face index, and splits it out into its two components.
231  * Then it looks up the filename on the model path. Sets the filename and
232  * face index accordingly. Also sets index_str to be the concatenation of the
233  * found filename with the face index, thus restoring the original input (but
234  * normalized to contain the full path.)
235  */
236 void FontPool::
237 lookup_filename(const string &str, string &index_str,
238  Filename &filename, int &face_index) {
239  int colon = (int)str.length() - 1;
240  // Scan backwards over digits for a colon.
241  while (colon >= 0 && isdigit(str[colon])) {
242  --colon;
243  }
244  if (colon >= 0 && str[colon] == ':') {
245  string digits = str.substr(colon + 1);
246  filename = str.substr(0, colon);
247  face_index = atoi(digits.c_str());
248  } else {
249  filename = str;
250  face_index = 0;
251  }
252 
253  // Now look up the filename on the model path.
255  vfs->resolve_filename(filename, get_model_path());
256 
257  std::ostringstream strm;
258  strm << filename << ":" << face_index;
259  index_str = strm.str();
260 }
261 
262 /**
263  * Initializes and/or returns the global pointer to the one FontPool object in
264  * the system.
265  */
266 FontPool *FontPool::
267 get_ptr() {
268  if (_global_ptr == nullptr) {
269  _global_ptr = new FontPool;
270  }
271  return _global_ptr;
272 }
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
nodePath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Loader
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
Definition: loader.h:42
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
FontPool
This is the preferred interface for loading fonts for the TextNode system.
Definition: fontPool.h:30
staticTextFont.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem::get_global_ptr
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Definition: virtualFileSystem.cxx:741
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FontPool::write
static void write(std::ostream &out)
Lists the contents of the font pool to the indicated output stream.
Definition: fontPool.cxx:32
dynamicTextFont.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
loader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Loader::get_global_ptr
static Loader * get_global_ptr()
Returns a pointer to the global Loader.
Definition: loader.I:212
TextFont
An encapsulation of a font; i.e.
Definition: textFont.h:32
VirtualFileSystem::resolve_filename
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
Definition: virtualFileSystem.cxx:640
fontPool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
StaticTextFont
A StaticTextFont is loaded up from a model that was previously generated via egg-mkfont,...
Definition: staticTextFont.h:38
config_express.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename::get_extension
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
ReferenceCount::get_ref_count
get_ref_count
Returns the current reference count.
Definition: referenceCount.h:53
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39