provide a default font

This commit is contained in:
David Rose 2003-01-31 21:09:26 +00:00
parent b65a885478
commit 7a7563ba2d
16 changed files with 4101 additions and 56 deletions

View File

@ -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]

View File

@ -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]

View File

@ -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 \

View File

@ -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";

View File

@ -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;

File diff suppressed because it is too large Load Diff

View 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

View File

@ -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

View File

@ -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
View 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
View 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
View 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

View File

@ -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

View File

@ -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");
}

View File

@ -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:

View File

@ -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"