mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
provide a default font
This commit is contained in:
parent
b65a885478
commit
7a7563ba2d
@ -390,6 +390,14 @@
|
||||
#define FREETYPE_LPATH
|
||||
#define FREETYPE_LIBS
|
||||
|
||||
// Define this true to compile in a default font, so every TextNode
|
||||
// will always have a font available without requiring the user to
|
||||
// specify one. Define it empty not to do this, saving a few
|
||||
// kilobytes on the generated library. Sorry, you can't pick a
|
||||
// particular font to be the default; it's hardcoded in the source.
|
||||
// This does require the Freetype library, above.
|
||||
#define COMPILE_IN_DEFAULT_FONT 1
|
||||
|
||||
// Is Maya installed? This matters only to programs in PANDATOOL.
|
||||
#define MAYA_LOCATION /usr/aw/maya3.0
|
||||
#defer MAYA_LIBS $[if $[WINDOWS_PLATFORM],Foundation.lib OpenMaya.lib OpenMayaAnim.lib,Foundation OpenMaya OpenMayaAnim]
|
||||
|
@ -22,6 +22,9 @@ $[cdefine HAVE_RAD_MSS]
|
||||
/* Define if we have Freetype 2.0 or better available. */
|
||||
$[cdefine HAVE_FREETYPE]
|
||||
|
||||
/* Define if we want to compile in a default font. */
|
||||
$[cdefine COMPILE_IN_DEFAULT_FONT]
|
||||
|
||||
/* Define if we have Maya available. */
|
||||
$[cdefine HAVE_MAYA]
|
||||
|
||||
|
@ -13,9 +13,11 @@
|
||||
|
||||
#define SOURCES \
|
||||
config_text.h \
|
||||
default_font.h \
|
||||
dynamicTextFont.I dynamicTextFont.h \
|
||||
dynamicTextGlyph.I dynamicTextGlyph.h \
|
||||
dynamicTextPage.I dynamicTextPage.h \
|
||||
fontPool.I fontPool.h \
|
||||
geomTextGlyph.I geomTextGlyph.h \
|
||||
staticTextFont.I staticTextFont.h \
|
||||
stringDecoder.I stringDecoder.h \
|
||||
@ -25,9 +27,11 @@
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
config_text.cxx \
|
||||
default_font.cxx \
|
||||
dynamicTextFont.cxx \
|
||||
dynamicTextGlyph.cxx \
|
||||
dynamicTextPage.cxx \
|
||||
fontPool.cxx \
|
||||
geomTextGlyph.cxx \
|
||||
stringDecoder.cxx \
|
||||
staticTextFont.cxx \
|
||||
@ -38,6 +42,7 @@
|
||||
dynamicTextFont.I dynamicTextFont.h \
|
||||
dynamicTextGlyph.I dynamicTextGlyph.h \
|
||||
dynamicTextPage.I dynamicTextPage.h \
|
||||
fontPool.I fontPool.h \
|
||||
geomTextGlyph.I geomTextGlyph.h \
|
||||
staticTextFont.I staticTextFont.h \
|
||||
stringDecoder.I stringDecoder.h \
|
||||
|
@ -45,6 +45,7 @@ const float text_pixels_per_unit = config_text.GetFloat("text-pixels-per-unit",
|
||||
const float text_scale_factor = config_text.GetFloat("text-scale-factor", 2.0f);
|
||||
const bool text_small_caps = config_text.GetBool("text-small-caps", false);
|
||||
const float text_small_caps_scale = config_text.GetFloat("text-small-caps-scale", 0.8f);
|
||||
const string text_default_font = config_text.GetString("text-default-font", "");
|
||||
|
||||
Texture::FilterType text_minfilter = Texture::FT_invalid;
|
||||
Texture::FilterType text_magfilter = Texture::FT_invalid;
|
||||
@ -79,11 +80,11 @@ init_libtext() {
|
||||
|
||||
string text_encoding = config_text.GetString("text-encoding", "iso8859");
|
||||
if (text_encoding == "iso8859") {
|
||||
TextNode::_default_encoding = TextNode::E_iso8859;
|
||||
TextNode::set_default_encoding(TextNode::E_iso8859);
|
||||
} else if (text_encoding == "utf8") {
|
||||
TextNode::_default_encoding = TextNode::E_utf8;
|
||||
TextNode::set_default_encoding(TextNode::E_utf8);
|
||||
} else if (text_encoding == "unicode") {
|
||||
TextNode::_default_encoding = TextNode::E_unicode;
|
||||
TextNode::set_default_encoding(TextNode::E_unicode);
|
||||
} else {
|
||||
text_cat.error()
|
||||
<< "Invalid text-encoding: " << text_encoding << "\n";
|
||||
|
@ -39,6 +39,7 @@ extern const float text_pixels_per_unit;
|
||||
extern const float text_scale_factor;
|
||||
extern const bool text_small_caps;
|
||||
extern const float text_small_caps_scale;
|
||||
extern const string text_default_font;
|
||||
|
||||
extern Texture::FilterType text_minfilter;
|
||||
extern Texture::FilterType text_magfilter;
|
||||
|
3365
panda/src/text/default_font.cxx
Normal file
3365
panda/src/text/default_font.cxx
Normal file
File diff suppressed because it is too large
Load Diff
32
panda/src/text/default_font.h
Normal file
32
panda/src/text/default_font.h
Normal file
@ -0,0 +1,32 @@
|
||||
// Filename: default_font.h
|
||||
// Created by: drose (31Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DEFAULT_FONT_H
|
||||
#define DEFAULT_FONT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#if defined(HAVE_FREETYPE) && defined(COMPILE_IN_DEFAULT_FONT)
|
||||
|
||||
extern const char default_font_data[];
|
||||
extern const int default_font_size;
|
||||
|
||||
#endif // HAVE_FREETYPE && COMPILE_IN_DEFAULT_FONT
|
||||
|
||||
#endif
|
||||
|
@ -52,33 +52,8 @@ static const float points_per_inch = 72.0f;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DynamicTextFont::
|
||||
DynamicTextFont(const Filename &font_filename, int face_index) {
|
||||
_texture_margin = text_texture_margin;
|
||||
_poly_margin = text_poly_margin;
|
||||
_page_x_size = text_page_x_size;
|
||||
_page_y_size = text_page_y_size;
|
||||
_point_size = text_point_size;
|
||||
_tex_pixels_per_unit = text_pixels_per_unit;
|
||||
_scale_factor = text_scale_factor;
|
||||
_small_caps = text_small_caps;
|
||||
_small_caps_scale = text_small_caps_scale;
|
||||
initialize();
|
||||
|
||||
// We don't necessarily want to use mipmaps, since we don't want to
|
||||
// regenerate those every time the texture changes, but we probably
|
||||
// do want at least linear filtering. Use whatever the Configrc
|
||||
// file suggests.
|
||||
_minfilter = text_minfilter;
|
||||
_magfilter = text_magfilter;
|
||||
|
||||
// Anisotropic filtering can help the look of the text, and doesn't
|
||||
// require generating mipmaps, but does require hardware support.
|
||||
_anisotropic_degree = text_anisotropic_degree;
|
||||
|
||||
|
||||
_preferred_page = 0;
|
||||
|
||||
if (!_ft_initialized) {
|
||||
initialize_ft_library();
|
||||
}
|
||||
if (!_ft_ok) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font " << font_filename
|
||||
@ -136,6 +111,50 @@ DynamicTextFont(const Filename &font_filename, int face_index) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::Constructor
|
||||
// Access: Published
|
||||
// Description: This constructor accepts a table of data representing
|
||||
// the font file, loaded from some source other than a
|
||||
// filename on disk.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DynamicTextFont::
|
||||
DynamicTextFont(const char *font_data, int data_length, int face_index) {
|
||||
initialize();
|
||||
|
||||
if (!_ft_ok) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font: FreeType library not initialized properly.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int error;
|
||||
error = FT_New_Memory_Face(_ft_library,
|
||||
(const FT_Byte *)font_data, data_length,
|
||||
face_index, &_face);
|
||||
|
||||
if (error == FT_Err_Unknown_File_Format) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font: unknown file format.\n";
|
||||
} else if (error) {
|
||||
text_cat.error()
|
||||
<< "Unable to read font: invalid.\n";
|
||||
|
||||
} else {
|
||||
string name = _face->family_name;
|
||||
if (_face->style_name != NULL) {
|
||||
name += " ";
|
||||
name += _face->style_name;
|
||||
}
|
||||
set_name(name);
|
||||
|
||||
text_cat.info()
|
||||
<< "Loaded font " << get_name() << "\n";
|
||||
_is_valid = true;
|
||||
reset_scale();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::Constructor
|
||||
// Access: Published, Virtual
|
||||
@ -334,6 +353,43 @@ get_glyph(int character, const TextGlyph *&glyph, float &glyph_scale) {
|
||||
return (glyph_index != 0 && glyph != (DynamicTextGlyph *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::initialize
|
||||
// Access: Private
|
||||
// Description: Called from both constructors to set up some internal
|
||||
// structures.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DynamicTextFont::
|
||||
initialize() {
|
||||
_texture_margin = text_texture_margin;
|
||||
_poly_margin = text_poly_margin;
|
||||
_page_x_size = text_page_x_size;
|
||||
_page_y_size = text_page_y_size;
|
||||
_point_size = text_point_size;
|
||||
_tex_pixels_per_unit = text_pixels_per_unit;
|
||||
_scale_factor = text_scale_factor;
|
||||
_small_caps = text_small_caps;
|
||||
_small_caps_scale = text_small_caps_scale;
|
||||
|
||||
// We don't necessarily want to use mipmaps, since we don't want to
|
||||
// regenerate those every time the texture changes, but we probably
|
||||
// do want at least linear filtering. Use whatever the Configrc
|
||||
// file suggests.
|
||||
_minfilter = text_minfilter;
|
||||
_magfilter = text_magfilter;
|
||||
|
||||
// Anisotropic filtering can help the look of the text, and doesn't
|
||||
// require generating mipmaps, but does require hardware support.
|
||||
_anisotropic_degree = text_anisotropic_degree;
|
||||
|
||||
|
||||
_preferred_page = 0;
|
||||
|
||||
if (!_ft_initialized) {
|
||||
initialize_ft_library();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::update_filters
|
||||
// Access: Private
|
||||
|
@ -45,6 +45,7 @@
|
||||
class EXPCL_PANDA DynamicTextFont : public TextFont {
|
||||
PUBLISHED:
|
||||
DynamicTextFont(const Filename &font_filename, int face_index = 0);
|
||||
DynamicTextFont(const char *font_data, int data_length, int face_index);
|
||||
virtual ~DynamicTextFont();
|
||||
|
||||
INLINE bool set_point_size(float point_size);
|
||||
@ -94,6 +95,7 @@ public:
|
||||
float &glyph_scale);
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
void update_filters();
|
||||
bool reset_scale();
|
||||
DynamicTextGlyph *make_glyph(int glyph_index);
|
||||
|
131
panda/src/text/fontPool.I
Normal file
131
panda/src/text/fontPool.I
Normal file
@ -0,0 +1,131 @@
|
||||
// Filename: fontPool.I
|
||||
// Created by: drose (31Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::has_font
|
||||
// Access: Public, Static
|
||||
// Description: Returns true if the font has ever been loaded,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool FontPool::
|
||||
has_font(const string &filename) {
|
||||
return get_ptr()->ns_has_font(filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::verify_font
|
||||
// Access: Public, Static
|
||||
// Description: Loads the given filename up into a font, if it has
|
||||
// not already been loaded, and returns true to indicate
|
||||
// success, or false to indicate failure. If this
|
||||
// returns true, it is guaranteed that a subsequent call
|
||||
// to load_font() with the same font name will
|
||||
// return a valid Font pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool FontPool::
|
||||
verify_font(const string &filename) {
|
||||
return load_font(filename) != (TextFont *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::load_font
|
||||
// Access: Public, Static
|
||||
// Description: Loads the given filename up into a font, if it has
|
||||
// not already been loaded, and returns the new font.
|
||||
// If a font with the same filename was previously
|
||||
// loaded, returns that one instead. If the font
|
||||
// file cannot be found, returns NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextFont *FontPool::
|
||||
load_font(const string &filename) {
|
||||
return get_ptr()->ns_load_font(filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::add_font
|
||||
// Access: Public, Static
|
||||
// Description: Adds the indicated already-loaded font to the
|
||||
// pool. The font will always replace any
|
||||
// previously-loaded font in the pool that had the
|
||||
// same filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void FontPool::
|
||||
add_font(const string &filename, TextFont *font) {
|
||||
get_ptr()->ns_add_font(filename, font);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::release_font
|
||||
// Access: Public, Static
|
||||
// Description: Removes the indicated font from the pool,
|
||||
// indicating it will never be loaded again; the font
|
||||
// may then be freed. If this function is never called,
|
||||
// a reference count will be maintained on every font
|
||||
// every loaded, and fonts will never be freed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void FontPool::
|
||||
release_font(const string &filename) {
|
||||
get_ptr()->ns_release_font(filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::release_all_fonts
|
||||
// Access: Public, Static
|
||||
// Description: Releases all fonts in the pool and restores the
|
||||
// pool to the empty state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void FontPool::
|
||||
release_all_fonts() {
|
||||
get_ptr()->ns_release_all_fonts();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::garbage_collect
|
||||
// Access: Public, Static
|
||||
// Description: Releases only those fonts in the pool that have a
|
||||
// reference count of exactly 1; i.e. only those
|
||||
// fonts that are not being used outside of the pool.
|
||||
// Returns the number of fonts released.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int FontPool::
|
||||
garbage_collect() {
|
||||
return get_ptr()->ns_garbage_collect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::list_contents
|
||||
// Access: Public, Static
|
||||
// Description: Lists the contents of the font pool to the
|
||||
// indicated output stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void FontPool::
|
||||
list_contents(ostream &out) {
|
||||
get_ptr()->ns_list_contents(out);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::Constructor
|
||||
// Access: Private
|
||||
// Description: The constructor is not intended to be called
|
||||
// directly; there's only supposed to be one FontPool
|
||||
// in the universe and it constructs itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE FontPool::
|
||||
FontPool() {
|
||||
}
|
234
panda/src/text/fontPool.cxx
Normal file
234
panda/src/text/fontPool.cxx
Normal file
@ -0,0 +1,234 @@
|
||||
// Filename: fontPool.cxx
|
||||
// Created by: drose (31Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "fontPool.h"
|
||||
#include "config_util.h"
|
||||
#include "config_express.h"
|
||||
#include "virtualFileSystem.h"
|
||||
#include "nodePath.h"
|
||||
#include "loader.h"
|
||||
|
||||
FontPool *FontPool::_global_ptr = (FontPool *)NULL;
|
||||
|
||||
static Loader model_loader;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::ns_has_font
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of has_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool FontPool::
|
||||
ns_has_font(const string &str) {
|
||||
Filename filename;
|
||||
int face_index;
|
||||
lookup_filename(str, filename, face_index);
|
||||
|
||||
Fonts::const_iterator ti;
|
||||
ti = _fonts.find(filename);
|
||||
if (ti != _fonts.end()) {
|
||||
// This font was previously loaded.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::ns_load_font
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of load_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TextFont *FontPool::
|
||||
ns_load_font(const string &str) {
|
||||
Filename filename;
|
||||
int face_index;
|
||||
lookup_filename(str, filename, face_index);
|
||||
|
||||
Fonts::const_iterator ti;
|
||||
ti = _fonts.find(filename);
|
||||
if (ti != _fonts.end()) {
|
||||
// This font was previously loaded.
|
||||
return (*ti).second;
|
||||
}
|
||||
|
||||
text_cat.info()
|
||||
<< "Loading font " << filename << "\n";
|
||||
|
||||
// Now, figure out how to load the font. If its filename extension
|
||||
// is "egg" or "bam", or if it's unspecified, assume it's a model
|
||||
// file, representing a static font.
|
||||
PT(TextFont) font;
|
||||
|
||||
string extension = filename.get_extension();
|
||||
if (extension.empty() || extension == "egg" || extension == "bam") {
|
||||
PT(PandaNode) node = model_loader.load_sync(filename);
|
||||
if (node != (PandaNode *)NULL) {
|
||||
// It is a model. Elevate all the priorities by 1, and make a
|
||||
// font out of it.
|
||||
NodePath np(node);
|
||||
np.adjust_all_priorities(1);
|
||||
font = new StaticTextFont(node);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
if (font == (TextFont *)NULL || !font->is_valid()) {
|
||||
// If we couldn't load the font as a model, try using FreeType to
|
||||
// load it as a font file.
|
||||
font = new DynamicTextFont(filename, face_index);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (font == (TextFont *)NULL || !font->is_valid()) {
|
||||
// This font was not found or could not be read.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_fonts[filename] = font;
|
||||
return font;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::ns_add_font
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of add_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FontPool::
|
||||
ns_add_font(const string &filename, TextFont *font) {
|
||||
// We blow away whatever font was there previously, if any.
|
||||
_fonts[filename] = font;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::ns_release_font
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of release_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FontPool::
|
||||
ns_release_font(const string &filename) {
|
||||
Fonts::iterator ti;
|
||||
ti = _fonts.find(filename);
|
||||
if (ti != _fonts.end()) {
|
||||
_fonts.erase(ti);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::ns_release_all_fonts
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of release_all_fonts().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FontPool::
|
||||
ns_release_all_fonts() {
|
||||
_fonts.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::ns_garbage_collect
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of garbage_collect().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int FontPool::
|
||||
ns_garbage_collect() {
|
||||
int num_released = 0;
|
||||
Fonts new_set;
|
||||
|
||||
Fonts::iterator ti;
|
||||
for (ti = _fonts.begin(); ti != _fonts.end(); ++ti) {
|
||||
TextFont *font = (*ti).second;
|
||||
if (font->get_ref_count() == 1) {
|
||||
if (text_cat.is_debug()) {
|
||||
text_cat.debug()
|
||||
<< "Releasing " << (*ti).first << "\n";
|
||||
}
|
||||
num_released++;
|
||||
} else {
|
||||
new_set.insert(new_set.end(), *ti);
|
||||
}
|
||||
}
|
||||
|
||||
_fonts.swap(new_set);
|
||||
return num_released;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::ns_list_contents
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of list_contents().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FontPool::
|
||||
ns_list_contents(ostream &out) {
|
||||
out << _fonts.size() << " fonts:\n";
|
||||
Fonts::iterator ti;
|
||||
for (ti = _fonts.begin(); ti != _fonts.end(); ++ti) {
|
||||
TextFont *font = (*ti).second;
|
||||
out << " " << (*ti).first
|
||||
<< " (count = " << font->get_ref_count() << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::lookup_filename
|
||||
// Access: Private, Static
|
||||
// Description: Accepts a font "filename", which might consist of a
|
||||
// filename followed by an optional colon and a face
|
||||
// index, and splits it out into its two components.
|
||||
// Then it looks up the filename on the model path.
|
||||
// Sets the filename and face index accordingly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FontPool::
|
||||
lookup_filename(const string &str,
|
||||
Filename &filename, int &face_index) {
|
||||
int colon = (int)str.length() - 1;
|
||||
// Scan backwards over digits for a colon.
|
||||
while (colon >= 0 && isdigit(str[colon])) {
|
||||
colon--;
|
||||
}
|
||||
if (colon >= 0 && str[colon] == ':') {
|
||||
string digits = str.substr(colon + 1);
|
||||
filename = str.substr(0, colon);
|
||||
face_index = atoi(digits.c_str());
|
||||
|
||||
} else {
|
||||
filename = str;
|
||||
face_index = 0;
|
||||
}
|
||||
|
||||
// Now look up the filename on the model path.
|
||||
if (use_vfs) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(filename, get_model_path());
|
||||
|
||||
} else {
|
||||
filename.resolve_filename(get_model_path());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FontPool::get_ptr
|
||||
// Access: Private, Static
|
||||
// Description: Initializes and/or returns the global pointer to the
|
||||
// one FontPool object in the system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FontPool *FontPool::
|
||||
get_ptr() {
|
||||
if (_global_ptr == (FontPool *)NULL) {
|
||||
_global_ptr = new FontPool;
|
||||
}
|
||||
return _global_ptr;
|
||||
}
|
75
panda/src/text/fontPool.h
Normal file
75
panda/src/text/fontPool.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Filename: fontPool.h
|
||||
// Created by: drose (31Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FONTPOOL_H
|
||||
#define FONTPOOL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "texture.h"
|
||||
|
||||
#include "filename.h"
|
||||
#include "pmap.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : FontPool
|
||||
// Description : This is the preferred interface for loading fonts for
|
||||
// the TextNode system. It is similar to ModelPool and
|
||||
// TexturePool in that it unifies references to the same
|
||||
// filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA FontPool {
|
||||
PUBLISHED:
|
||||
// These functions take string parameters instead of Filenames
|
||||
// because that's somewhat more convenient to the scripting
|
||||
// language.
|
||||
INLINE static bool has_font(const string &filename);
|
||||
INLINE static bool verify_font(const string &filename);
|
||||
INLINE static TextFont *load_font(const string &filename);
|
||||
INLINE static void add_font(const string &filename, TextFont *font);
|
||||
INLINE static void release_font(const string &filename);
|
||||
INLINE static void release_all_fonts();
|
||||
|
||||
INLINE static int garbage_collect();
|
||||
|
||||
INLINE static void list_contents(ostream &out);
|
||||
|
||||
private:
|
||||
INLINE FontPool();
|
||||
|
||||
bool ns_has_font(const string &str);
|
||||
TextFont *ns_load_font(const string &str);
|
||||
void ns_add_font(const string &filename, TextFont *font);
|
||||
void ns_release_font(const string &filename);
|
||||
void ns_release_all_fonts();
|
||||
int ns_garbage_collect();
|
||||
void ns_list_contents(ostream &out);
|
||||
|
||||
static void lookup_filename(const string &str,
|
||||
Filename &filename, int &face_index);
|
||||
|
||||
static FontPool *get_ptr();
|
||||
|
||||
static FontPool *_global_ptr;
|
||||
typedef pmap<string, PT(TextFont) > Fonts;
|
||||
Fonts _fonts;
|
||||
};
|
||||
|
||||
#include "fontPool.I"
|
||||
|
||||
#endif
|
@ -44,7 +44,9 @@ thaw() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_font
|
||||
// Access: Published
|
||||
// Description: Sets the font that will be used when making text.
|
||||
// Description: Sets the font that will be used when making text. If
|
||||
// this is set to NULL, the default font will be used,
|
||||
// which can be set via set_default_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
set_font(TextFont *font) {
|
||||
@ -57,13 +59,45 @@ set_font(TextFont *font) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_font
|
||||
// Access: Published
|
||||
// Description: Returns the font currently in use.
|
||||
// Description: Returns the font currently in use, if any. If this
|
||||
// returns NULL, the default font will be used, which
|
||||
// can be retrieved via get_default_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextFont *TextNode::
|
||||
get_font() const {
|
||||
return _font;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_default_font
|
||||
// Access: Published, Static
|
||||
// Description: Specifies the default font to be used for any
|
||||
// TextNode whose font is uninitialized or NULL. See
|
||||
// set_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
set_default_font(TextFont *font) {
|
||||
// If the user overrides the default, we don't need to try to load
|
||||
// whatever it would have been.
|
||||
_loaded_default_font = true;
|
||||
_default_font = font;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_default_font
|
||||
// Access: Published, Static
|
||||
// Description: Specifies the default font to be used for any
|
||||
// TextNode whose font is uninitialized or NULL. See
|
||||
// set_font().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextFont *TextNode::
|
||||
get_default_font() {
|
||||
if (!_loaded_default_font) {
|
||||
load_default_font();
|
||||
}
|
||||
return _default_font;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_encoding
|
||||
// Access: Published
|
||||
@ -96,6 +130,30 @@ get_encoding() const {
|
||||
return _encoding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_default_encoding
|
||||
// Access: Published, Static
|
||||
// Description: Specifies the default encoding to be used for all
|
||||
// subsequently created TextNode objects. See
|
||||
// set_encoding().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
set_default_encoding(TextNode::Encoding encoding) {
|
||||
_default_encoding = encoding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_default_encoding
|
||||
// Access: Published, Static
|
||||
// Description: Specifies the default encoding to be used for all
|
||||
// subsequently created TextNode objects. See
|
||||
// set_encoding().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextNode::Encoding TextNode::
|
||||
get_default_encoding() {
|
||||
return _default_encoding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_expand_amp
|
||||
// Access: Published
|
||||
|
@ -20,6 +20,9 @@
|
||||
#include "textGlyph.h"
|
||||
#include "stringDecoder.h"
|
||||
#include "config_text.h"
|
||||
#include "fontPool.h"
|
||||
#include "default_font.h"
|
||||
#include "dynamicTextFont.h"
|
||||
|
||||
#include "compose_matrix.h"
|
||||
#include "geom.h"
|
||||
@ -47,6 +50,8 @@
|
||||
|
||||
TypeHandle TextNode::_type_handle;
|
||||
|
||||
PT(TextFont) TextNode::_default_font;
|
||||
bool TextNode::_loaded_default_font = false;
|
||||
TextNode::Encoding TextNode::_default_encoding;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -255,7 +260,16 @@ generate() {
|
||||
// Now build a new sub-tree for all the text components.
|
||||
PT(PandaNode) root = new PandaNode(get_text());
|
||||
|
||||
if (!has_text() || _font.is_null()) {
|
||||
if (!has_text()) {
|
||||
return root;
|
||||
}
|
||||
|
||||
TextFont *font = get_font();
|
||||
if (font == (TextFont *)NULL) {
|
||||
font = get_default_font();
|
||||
}
|
||||
|
||||
if (font == (TextFont *)NULL) {
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -270,13 +284,15 @@ generate() {
|
||||
|
||||
wstring wtext = get_wtext();
|
||||
if (has_wordwrap()) {
|
||||
wtext = _font->wordwrap_to(wtext, _wordwrap_width, false);
|
||||
wtext = font->wordwrap_to(wtext, _wordwrap_width, false);
|
||||
}
|
||||
|
||||
// Assemble the text.
|
||||
LVector2f ul, lr;
|
||||
int num_rows = 0;
|
||||
PT(PandaNode) text_root = assemble_text(wtext.begin(), wtext.end(), ul, lr, num_rows);
|
||||
PT(PandaNode) text_root =
|
||||
assemble_text(wtext.begin(), wtext.end(), font,
|
||||
ul, lr, num_rows);
|
||||
|
||||
// Parent the text in.
|
||||
PT(PandaNode) text = new PandaNode("text");
|
||||
@ -821,18 +837,28 @@ do_measure() {
|
||||
_lr3d.set(0.0f, 0.0f, 0.0f);
|
||||
_num_rows = 0;
|
||||
|
||||
if (!has_text() || _font.is_null()) {
|
||||
if (!has_text()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TextFont *font = get_font();
|
||||
if (font == (TextFont *)NULL) {
|
||||
font = get_default_font();
|
||||
}
|
||||
|
||||
if (font == (TextFont *)NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wstring wtext = get_wtext();
|
||||
if (has_wordwrap()) {
|
||||
wtext = _font->wordwrap_to(wtext, _wordwrap_width, false);
|
||||
wtext = font->wordwrap_to(wtext, _wordwrap_width, false);
|
||||
}
|
||||
|
||||
LVector2f ul, lr;
|
||||
int num_rows = 0;
|
||||
measure_text(wtext.begin(), wtext.end(), ul, lr, num_rows);
|
||||
measure_text(wtext.begin(), wtext.end(), font,
|
||||
ul, lr, num_rows);
|
||||
|
||||
_num_rows = num_rows;
|
||||
_ul2d = ul;
|
||||
@ -857,25 +883,23 @@ do_measure() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float TextNode::
|
||||
assemble_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
PandaNode *dest) {
|
||||
nassertr(_font != (TextFont *)NULL, 0.0f);
|
||||
|
||||
TextFont *font, PandaNode *dest) {
|
||||
float xpos = 0.0f;
|
||||
while (si != send && (*si) != '\n') {
|
||||
wchar_t character = *si;
|
||||
|
||||
if (character == ' ') {
|
||||
// A space is a special case.
|
||||
xpos += _font->get_space_advance();
|
||||
xpos += font->get_space_advance();
|
||||
|
||||
} else {
|
||||
// A printable character.
|
||||
|
||||
const TextGlyph *glyph;
|
||||
float glyph_scale;
|
||||
if (!_font->get_glyph(character, glyph, glyph_scale)) {
|
||||
if (!font->get_glyph(character, glyph, glyph_scale)) {
|
||||
text_cat.warning()
|
||||
<< "No definition in " << _font->get_name()
|
||||
<< "No definition in " << font->get_name()
|
||||
<< " for character " << character;
|
||||
if (character < 128 && isprint((unsigned int)character)) {
|
||||
text_cat.warning(false)
|
||||
@ -918,8 +942,7 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(PandaNode) TextNode::
|
||||
assemble_text(wstring::iterator si, const wstring::iterator &send,
|
||||
LVector2f &ul, LVector2f &lr, int &num_rows) {
|
||||
nassertr(_font != (TextFont *)NULL, (PandaNode *)NULL);
|
||||
TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) {
|
||||
float line_height = get_line_height();
|
||||
|
||||
ul.set(0.0f, 0.8f * line_height);
|
||||
@ -936,7 +959,7 @@ assemble_text(wstring::iterator si, const wstring::iterator &send,
|
||||
nassertr(strlen(numstr) < 20, root_node);
|
||||
|
||||
PT(PandaNode) row = new PandaNode(numstr);
|
||||
float row_width = assemble_row(si, send, row);
|
||||
float row_width = assemble_row(si, send, font, row);
|
||||
if (si != send) {
|
||||
// Skip past the newline.
|
||||
++si;
|
||||
@ -988,21 +1011,22 @@ assemble_text(wstring::iterator si, const wstring::iterator &send,
|
||||
// it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float TextNode::
|
||||
measure_row(wstring::iterator &si, const wstring::iterator &send) {
|
||||
measure_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
TextFont *font) {
|
||||
float xpos = 0.0f;
|
||||
while (si != send && *si != '\n') {
|
||||
wchar_t character = *si;
|
||||
|
||||
if (character == ' ') {
|
||||
// A space is a special case.
|
||||
xpos += _font->get_space_advance();
|
||||
xpos += font->get_space_advance();
|
||||
|
||||
} else {
|
||||
// A printable character.
|
||||
|
||||
const TextGlyph *glyph;
|
||||
float glyph_scale;
|
||||
if (_font->get_glyph(character, glyph, glyph_scale)) {
|
||||
if (font->get_glyph(character, glyph, glyph_scale)) {
|
||||
xpos += glyph->get_advance() * glyph_scale;
|
||||
}
|
||||
}
|
||||
@ -1020,8 +1044,7 @@ measure_row(wstring::iterator &si, const wstring::iterator &send) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
measure_text(wstring::iterator si, const wstring::iterator &send,
|
||||
LVector2f &ul, LVector2f &lr, int &num_rows) {
|
||||
nassertv(_font != (TextFont *)NULL);
|
||||
TextFont *font, LVector2f &ul, LVector2f &lr, int &num_rows) {
|
||||
float line_height = get_line_height();
|
||||
|
||||
ul.set(0.0f, 0.8f * line_height);
|
||||
@ -1029,7 +1052,7 @@ measure_text(wstring::iterator si, const wstring::iterator &send,
|
||||
|
||||
float posy = 0.0f;
|
||||
while (si != send) {
|
||||
float row_width = measure_row(si, send);
|
||||
float row_width = measure_row(si, send, font);
|
||||
if (si != send) {
|
||||
// Skip past the newline.
|
||||
++si;
|
||||
@ -1268,3 +1291,40 @@ make_card_with_border() {
|
||||
|
||||
return card_geode.p();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::load_default_font
|
||||
// Access: Private, Static
|
||||
// Description: This functin is called once (or never), the first
|
||||
// time someone attempts to render a TextNode using the
|
||||
// default font. It should attempt to load the default
|
||||
// font, using the compiled-in version if it is
|
||||
// available, or whatever system file may be named in
|
||||
// Configrc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
load_default_font() {
|
||||
_loaded_default_font = true;
|
||||
|
||||
if (!text_default_font.empty()) {
|
||||
// First, attempt to load the user-specified filename.
|
||||
_default_font = FontPool::load_font(text_default_font);
|
||||
if (_default_font->is_valid()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Then, attempt to load the compiled-in font, if we have one.
|
||||
#if defined(HAVE_FREETYPE) && defined(COMPILE_IN_DEFAULT_FONT)
|
||||
_default_font = new DynamicTextFont(default_font_data, default_font_size, 0);
|
||||
if (_default_font->is_valid()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Finally, fall back to a hardcoded font file, which we hope is on
|
||||
// the model path. (Use text_default_font, above, if you don't want
|
||||
// to use this file and would prefer to specify a different font
|
||||
// file instead.)
|
||||
_default_font = FontPool::load_font("cmss12");
|
||||
}
|
||||
|
@ -75,9 +75,15 @@ PUBLISHED:
|
||||
INLINE void set_font(TextFont *font);
|
||||
INLINE TextFont *get_font() const;
|
||||
|
||||
INLINE static void set_default_font(TextFont *);
|
||||
INLINE static TextFont *get_default_font();
|
||||
|
||||
INLINE void set_encoding(Encoding encoding);
|
||||
INLINE Encoding get_encoding() const;
|
||||
|
||||
INLINE static void set_default_encoding(Encoding encoding);
|
||||
INLINE static Encoding get_default_encoding();
|
||||
|
||||
INLINE void set_expand_amp(bool expand_amp);
|
||||
INLINE bool get_expand_amp() const;
|
||||
|
||||
@ -243,12 +249,15 @@ private:
|
||||
void do_measure();
|
||||
|
||||
#ifndef CPPPARSER // interrogate has a bit of trouble with wstring.
|
||||
float assemble_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
PandaNode *dest);
|
||||
float assemble_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
TextFont *font, PandaNode *dest);
|
||||
PT(PandaNode) assemble_text(wstring::iterator si, const wstring::iterator &send,
|
||||
TextFont *font,
|
||||
LVector2f &ul, LVector2f &lr, int &num_rows);
|
||||
float measure_row(wstring::iterator &si, const wstring::iterator &send);
|
||||
float measure_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
TextFont *font);
|
||||
void measure_text(wstring::iterator si, const wstring::iterator &send,
|
||||
TextFont *font,
|
||||
LVector2f &ul, LVector2f &lr, int &num_rows);
|
||||
#endif // CPPPARSER
|
||||
|
||||
@ -256,6 +265,8 @@ private:
|
||||
PT(PandaNode) make_card();
|
||||
PT(PandaNode) make_card_with_border();
|
||||
|
||||
static void load_default_font();
|
||||
|
||||
PT(TextFont) _font;
|
||||
PT(PandaNode) _internal_geom;
|
||||
|
||||
@ -311,7 +322,8 @@ private:
|
||||
LPoint3f _ul3d, _lr3d;
|
||||
int _num_rows;
|
||||
|
||||
public:
|
||||
static PT(TextFont) _default_font;
|
||||
static bool _loaded_default_font;
|
||||
static Encoding _default_encoding;
|
||||
|
||||
public:
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include "config_text.cxx"
|
||||
#include "default_font.cxx"
|
||||
#include "dynamicTextFont.cxx"
|
||||
#include "dynamicTextGlyph.cxx"
|
||||
#include "dynamicTextPage.cxx"
|
||||
#include "fontPool.cxx"
|
||||
#include "geomTextGlyph.cxx"
|
||||
#include "staticTextFont.cxx"
|
||||
#include "stringDecoder.cxx"
|
||||
|
Loading…
x
Reference in New Issue
Block a user