From 00e38798efb2f8bbb550677f8d57e2fd483570dc Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 8 Feb 2002 23:35:09 +0000 Subject: [PATCH] split TextFont into TextFont and StaticTextFont, preparing for DynamicTextFont --- direct/src/showbase/Loader.py | 6 +- panda/src/text/Sources.pp | 14 +- panda/src/text/config_text.cxx | 2 + panda/src/text/staticTextFont.I | 18 ++ panda/src/text/staticTextFont.cxx | 297 +++++++++++++++++++++++++++++ panda/src/text/staticTextFont.h | 89 +++++++++ panda/src/text/textFont.I | 23 +-- panda/src/text/textFont.cxx | 264 ++----------------------- panda/src/text/textFont.h | 60 +++--- panda/src/text/textGlyph.I | 97 ++++++++++ panda/src/text/textGlyph.cxx | 19 ++ panda/src/text/textGlyph.h | 53 +++++ panda/src/text/textNode.cxx | 23 +-- panda/src/text/text_composite1.cxx | 2 + 14 files changed, 643 insertions(+), 324 deletions(-) create mode 100644 panda/src/text/staticTextFont.I create mode 100644 panda/src/text/staticTextFont.cxx create mode 100644 panda/src/text/staticTextFont.h create mode 100644 panda/src/text/textGlyph.I create mode 100644 panda/src/text/textGlyph.cxx create mode 100644 panda/src/text/textGlyph.h diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index b5848cf24a..6e69db39cb 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -108,7 +108,11 @@ class Loader: nodePath = hidden.attachNewNode(node) nodePath.adjustAllPriorities(priority) # Now create text font from the node - font = TextFont(node) + # Temporary try..except for old pandas. + try: + font = StaticTextFont(node) + except: + font = TextFont(node) # And remove node path nodePath.removeNode() return font diff --git a/panda/src/text/Sources.pp b/panda/src/text/Sources.pp index 83524096bc..e0ad683247 100644 --- a/panda/src/text/Sources.pp +++ b/panda/src/text/Sources.pp @@ -10,13 +10,21 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx #define SOURCES \ - config_text.h textFont.I textFont.h \ + config_text.h \ + staticTextFont.I staticTextFont.h \ + textFont.I textFont.h \ + textGlyph.I textGlyph.h \ textNode.I textNode.h textNode.cxx - #define INCLUDED_SOURCES config_text.cxx textFont.cxx + #define INCLUDED_SOURCES \ + config_text.cxx staticTextFont.cxx textFont.cxx textGlyph.cxx #define INSTALL_HEADERS \ - config_text.h textFont.I textFont.h textNode.I textNode.h + config_text.h \ + staticTextFont.I staticTextFont.h \ + textFont.I textFont.h \ + textGlyph.I textGlyph.h \ + textNode.I textNode.h #define IGATESCAN all diff --git a/panda/src/text/config_text.cxx b/panda/src/text/config_text.cxx index 00aef727b6..69c8813e24 100644 --- a/panda/src/text/config_text.cxx +++ b/panda/src/text/config_text.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "config_text.h" +#include "staticTextFont.h" #include "textFont.h" #include "textNode.h" @@ -26,6 +27,7 @@ Configure(config_text); NotifyCategoryDef(text, ""); ConfigureFn(config_text) { + StaticTextFont::init_type(); TextFont::init_type(); TextNode::init_type(); } diff --git a/panda/src/text/staticTextFont.I b/panda/src/text/staticTextFont.I new file mode 100644 index 0000000000..0332662000 --- /dev/null +++ b/panda/src/text/staticTextFont.I @@ -0,0 +1,18 @@ +// Filename: staticTextFont.I +// Created by: drose (03May01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 . +// +//////////////////////////////////////////////////////////////////// + diff --git a/panda/src/text/staticTextFont.cxx b/panda/src/text/staticTextFont.cxx new file mode 100644 index 0000000000..a2e345e3b8 --- /dev/null +++ b/panda/src/text/staticTextFont.cxx @@ -0,0 +1,297 @@ +// Filename: staticTextFont.cxx +// Created by: drose (03May01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "staticTextFont.h" +#include "config_text.h" + +#include "geom.h" +#include "geomPoint.h" +#include "geomNode.h" +#include "namedNode.h" +#include "renderRelation.h" + +TypeHandle StaticTextFont::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::Constructor +// Access: Published +// Description: The constructor expects the root node to a model +// generated via egg-mkfont, which consists of a set of +// models, one per each character in the font. +//////////////////////////////////////////////////////////////////// +StaticTextFont:: +StaticTextFont(Node *font_def) { + nassertv(font_def != (Node *)NULL); + _font = font_def; + _glyphs.clear(); + + find_characters(font_def); + + if (_font->is_of_type(NamedNode::get_class_type())) { + NamedNode *named_node = DCAST(NamedNode, _font); + set_name(named_node->get_name()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::Destructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +StaticTextFont:: +~StaticTextFont() { +} + + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::write +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void StaticTextFont:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << "StaticTextFont " << get_name() << "; " + << _glyphs.size() << " characters available in font:\n"; + Glyphs::const_iterator gi; + + // Figure out which symbols we have. We collect lowercase letters, + // uppercase letters, and digits together for the user's + // convenience. + static const int num_letters = 26; + static const int num_digits = 10; + bool lowercase[num_letters]; + bool uppercase[num_letters]; + bool digits[num_digits]; + + memset(lowercase, 0, sizeof(bool) * num_letters); + memset(uppercase, 0, sizeof(bool) * num_letters); + memset(digits, 0, sizeof(bool) * num_digits); + + int count_lowercase = 0; + int count_uppercase = 0; + int count_digits = 0; + + for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) { + int ch = (*gi).first; + if (islower(ch)) { + count_lowercase++; + lowercase[ch - 'a'] = true; + + } else if (isupper(ch)) { + count_uppercase++; + uppercase[ch - 'A'] = true; + + } else if (isdigit(ch)) { + count_digits++; + digits[ch - '0'] = true; + } + } + + if (count_lowercase == num_letters) { + indent(out, indent_level + 2) + << "All lowercase letters\n"; + + } else if (count_lowercase > 0) { + indent(out, indent_level + 2) + << "Some lowercase letters: "; + for (int i = 0; i < num_letters; i++) { + if (lowercase[i]) { + out << (char)(i + 'a'); + } + } + out << "\n"; + } + + if (count_uppercase == num_letters) { + indent(out, indent_level + 2) + << "All uppercase letters\n"; + + } else if (count_uppercase > 0) { + indent(out, indent_level + 2) + << "Some uppercase letters: "; + for (int i = 0; i < num_letters; i++) { + if (uppercase[i]) { + out << (char)(i + 'A'); + } + } + out << "\n"; + } + + if (count_digits == num_digits) { + indent(out, indent_level + 2) + << "All digits\n"; + + } else if (count_digits > 0) { + indent(out, indent_level + 2) + << "Some digits: "; + for (int i = 0; i < num_digits; i++) { + if (digits[i]) { + out << (char)(i + '0'); + } + } + out << "\n"; + } + + for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) { + int ch = (*gi).first; + if (!isalnum(ch)) { + indent(out, indent_level + 2) + << ch; + if (isprint(ch)) { + out << " = '" << (char)ch << "'\n"; + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::get_glyph +// Access: Public, Virtual +// Description: Returns the glyph associated with the given character +// code, or NULL if there is no such glyph. +//////////////////////////////////////////////////////////////////// +const TextGlyph *StaticTextFont:: +get_glyph(int character) const { + Glyphs::const_iterator gi = _glyphs.find(character); + if (gi == _glyphs.end()) { + // No definition for this character. + return (TextGlyph *)NULL; + } else { + return &(*gi).second; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::find_character_gsets +// Access: Private +// Description: Given that 'root' is a Node containing at least a +// polygon and a point which define the character's +// appearance and kern position, respectively, +// recursively walk the hierarchy and root and locate +// those two Geoms. +//////////////////////////////////////////////////////////////////// +bool StaticTextFont:: +find_character_gsets(Node *root, Geom *&ch, GeomPoint *&dot, + AllTransitionsWrapper &trans) { + if (root->is_of_type(GeomNode::get_class_type())) { + GeomNode *geode = (GeomNode *)root; + + bool found = false; + for (int i = 0; i < geode->get_num_geoms(); i++) { + dDrawable *geom = geode->get_geom(i); + if (geom->is_of_type(GeomPoint::get_class_type())) { + dot = DCAST(GeomPoint, geom); + + } else if (geom->is_of_type(Geom::get_class_type())) { + ch = DCAST(Geom, geom); + found = true; + } + } + return found; + + } else { + TypeHandle graph_type = RenderRelation::get_class_type(); + int num_children = root->get_num_children(graph_type); + for (int i = 0; i < num_children; i++) { + NodeRelation *child_arc = root->get_child(graph_type, i); + if (find_character_gsets(child_arc->get_child(), ch, dot, trans)) { + trans.extract_from(child_arc); + } + } + return false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::find_characters +// Access: Private +// Description: Walk the hierarchy beginning at the indicated root +// and locate any nodes whose names are just integers. +// These are taken to be characters, and their +// definitions and kern informations are retrieved. +//////////////////////////////////////////////////////////////////// +void StaticTextFont:: +find_characters(Node *root) { + string name; + if (root->is_of_type(NamedNode::get_class_type())) { + name = DCAST(NamedNode, root)->get_name(); + } + + bool all_digits = !name.empty(); + const char *p = name.c_str(); + while (all_digits && *p != '\0') { + // VC++ complains if we treat an int as a bool, so we have to do + // this != 0 comparsion on the int isdigit() function to shut it + // up. + all_digits = (isdigit(*p) != 0); + p++; + } + + if (all_digits) { + int character = atoi(name.c_str()); + Geom *ch = NULL; + GeomPoint *dot = NULL; + AllTransitionsWrapper trans; + find_character_gsets(root, ch, dot, trans); + if (dot != NULL) { + // Get the first vertex from the "dot" geoset. This will be the + // origin of the next character. + PTA_Vertexf alist; + PTA_ushort ilist; + float width; + dot->get_coords(alist, ilist); + if (ilist.empty()) { + width = alist[0][0]; + } else { + width = alist[ilist[0]][0]; + } + + _glyphs[character] = TextGlyph(ch, trans, width); + } + + } else if (name == "ds") { + // The group "ds" is a special node that indicate's the font's + // design size, or line height. + + Geom *ch = NULL; + GeomPoint *dot = NULL; + AllTransitionsWrapper trans; + find_character_gsets(root, ch, dot, trans); + if (dot != NULL) { + // Get the first vertex from the "dot" geoset. This will be the + // design size indicator. + PTA_Vertexf alist; + PTA_ushort ilist; + dot->get_coords(alist, ilist); + if (ilist.empty()) { + _line_height = alist[0][2]; + } else { + _line_height = alist[ilist[0]][2]; + } + } + + } else { + TypeHandle graph_type = RenderRelation::get_class_type(); + int num_children = root->get_num_children(graph_type); + for (int i = 0; i < num_children; i++) { + NodeRelation *child_arc = root->get_child(graph_type, i); + find_characters(child_arc->get_child()); + } + } +} diff --git a/panda/src/text/staticTextFont.h b/panda/src/text/staticTextFont.h new file mode 100644 index 0000000000..73fbb605c0 --- /dev/null +++ b/panda/src/text/staticTextFont.h @@ -0,0 +1,89 @@ +// Filename: staticTextFont.h +// Created by: drose (03May01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 STATICTEXTFONT_H +#define STATICTEXTFONT_H + +#include + +#include "config_text.h" +#include "textFont.h" +#include "textGlyph.h" + +#include +#include +#include +#include + +#include "pmap.h" + +class Node; +class Geom; +class GeomPoint; + +//////////////////////////////////////////////////////////////////// +// Class : StaticTextFont +// Description : A StaticTextFont is loaded up from a model that was +// previously generated via egg-mkfont, and contains all +// of its glyphs already generated and available for +// use. It doesn't require linking with any external +// libraries like FreeType. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA StaticTextFont : public TextFont { +PUBLISHED: + StaticTextFont(Node *font_def); + virtual ~StaticTextFont(); + + virtual void write(ostream &out, int indent_level) const; + +public: + virtual const TextGlyph *get_glyph(int character) const; + +private: + bool find_character_gsets(Node *root, Geom *&ch, GeomPoint *&dot, + AllTransitionsWrapper &trans); + void find_characters(Node *root); + + typedef pmap Glyphs; + Glyphs _glyphs; + float _font_height; + PT_Node _font; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TextFont::init_type(); + register_type(_type_handle, "StaticTextFont", + TextFont::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + + friend class TextNode; +}; + +#include "staticTextFont.I" + +#endif diff --git a/panda/src/text/textFont.I b/panda/src/text/textFont.I index 351fe85125..aa56fa81fb 100644 --- a/panda/src/text/textFont.I +++ b/panda/src/text/textFont.I @@ -1,5 +1,5 @@ // Filename: textFont.I -// Created by: drose (03May01) +// Created by: drose (08Feb02) // //////////////////////////////////////////////////////////////////// // @@ -21,26 +21,9 @@ // Function: TextFont::get_line_height // Access: Published // Description: Returns the number of units high each line of text -// is. This is based on the font. +// is. //////////////////////////////////////////////////////////////////// INLINE float TextFont:: get_line_height() const { - return _font_height; -} - -//////////////////////////////////////////////////////////////////// -// Function: TextFont::get_line_height -// Access: Published -// Description: Returns the number of units high each line of text -// is. This is based on the font. -//////////////////////////////////////////////////////////////////// -INLINE const TextFont::CharDef *TextFont:: -get_char(int character) const { - CharDefs::const_iterator cdi = _defs.find(character); - if (cdi == _defs.end()) { - // No definition for this character. - return (CharDef *)NULL; - } else { - return &(*cdi).second; - } + return _line_height; } diff --git a/panda/src/text/textFont.cxx b/panda/src/text/textFont.cxx index 19aa03227c..6acb127bd9 100644 --- a/panda/src/text/textFont.cxx +++ b/panda/src/text/textFont.cxx @@ -1,5 +1,5 @@ // Filename: textFont.cxx -// Created by: drose (03May01) +// Created by: drose (08Feb02) // //////////////////////////////////////////////////////////////////// // @@ -18,17 +18,11 @@ #include "textFont.h" #include "config_text.h" - -#include "geom.h" -#include "geomPoint.h" -#include "geomNode.h" -#include "namedNode.h" -#include "renderRelation.h" - #include "ctype.h" TypeHandle TextFont::_type_handle; + //////////////////////////////////////////////////////////////////// // Function: isblank // Description: An internal function, similar to isspace(), except it @@ -39,40 +33,19 @@ isblank(char ch) { return (ch == ' ' || ch == '\t'); } -//////////////////////////////////////////////////////////////////// -// Function: TextFont::CharDef::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -TextFont::CharDef:: -CharDef(Geom *geom, float width, const AllTransitionsWrapper &trans) : - _geom(geom), _width(width), _trans(trans) { } - //////////////////////////////////////////////////////////////////// // Function: TextFont::Constructor -// Access: Published -// Description: The constructor expects the root node to a model -// generated via egg-mkfont, which consists of a set of -// models, one per each character in the font. +// Access: Public +// Description: //////////////////////////////////////////////////////////////////// TextFont:: -TextFont(Node *font_def) { - nassertv(font_def != (Node *)NULL); - _font = font_def; - _defs.clear(); - _font_height = 1.0; - - find_characters(font_def); - - if (_font->is_of_type(NamedNode::get_class_type())) { - NamedNode *named_node = DCAST(NamedNode, _font); - set_name(named_node->get_name()); - } +TextFont() { + _line_height = 1.0; } //////////////////////////////////////////////////////////////////// // Function: TextFont::Destructor -// Access: Published +// Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// TextFont:: @@ -86,19 +59,19 @@ TextFont:: // or 0.0 if the character is not known. //////////////////////////////////////////////////////////////////// float TextFont:: -calc_width(char ch) const { +calc_width(int ch) const { if (ch == ' ') { // A space is a special case. return 0.25; } - CharDefs::const_iterator cdi = _defs.find(ch); - if (cdi == _defs.end()) { + const TextGlyph *glyph = get_glyph(ch); + if (glyph == (TextGlyph *)NULL) { // Unknown character. return 0.0; } - return (*cdi).second._width; + return glyph->get_advance(); } //////////////////////////////////////////////////////////////////// @@ -242,224 +215,13 @@ wordwrap_to(const string &text, float wordwrap_width, return output_text; } - //////////////////////////////////////////////////////////////////// // Function: TextFont::write -// Access: Published +// Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// void TextFont:: write(ostream &out, int indent_level) const { indent(out, indent_level) - << "TextFont " << get_name() << "; " - << _defs.size() << " characters available in font:\n"; - CharDefs::const_iterator di; - - // Figure out which symbols we have. We collect lowercase letters, - // uppercase letters, and digits together for the user's - // convenience. - static const int num_letters = 26; - static const int num_digits = 10; - bool lowercase[num_letters]; - bool uppercase[num_letters]; - bool digits[num_digits]; - - memset(lowercase, 0, sizeof(bool) * num_letters); - memset(uppercase, 0, sizeof(bool) * num_letters); - memset(digits, 0, sizeof(bool) * num_digits); - - int count_lowercase = 0; - int count_uppercase = 0; - int count_digits = 0; - - for (di = _defs.begin(); di != _defs.end(); ++di) { - int ch = (*di).first; - if (islower(ch)) { - count_lowercase++; - lowercase[ch - 'a'] = true; - - } else if (isupper(ch)) { - count_uppercase++; - uppercase[ch - 'A'] = true; - - } else if (isdigit(ch)) { - count_digits++; - digits[ch - '0'] = true; - } - } - - if (count_lowercase == num_letters) { - indent(out, indent_level + 2) - << "All lowercase letters\n"; - - } else if (count_lowercase > 0) { - indent(out, indent_level + 2) - << "Some lowercase letters: "; - for (int i = 0; i < num_letters; i++) { - if (lowercase[i]) { - out << (char)(i + 'a'); - } - } - out << "\n"; - } - - if (count_uppercase == num_letters) { - indent(out, indent_level + 2) - << "All uppercase letters\n"; - - } else if (count_uppercase > 0) { - indent(out, indent_level + 2) - << "Some uppercase letters: "; - for (int i = 0; i < num_letters; i++) { - if (uppercase[i]) { - out << (char)(i + 'A'); - } - } - out << "\n"; - } - - if (count_digits == num_digits) { - indent(out, indent_level + 2) - << "All digits\n"; - - } else if (count_digits > 0) { - indent(out, indent_level + 2) - << "Some digits: "; - for (int i = 0; i < num_digits; i++) { - if (digits[i]) { - out << (char)(i + '0'); - } - } - out << "\n"; - } - - for (di = _defs.begin(); di != _defs.end(); ++di) { - int ch = (*di).first; - if (!isalnum(ch)) { - indent(out, indent_level + 2) - << ch; - if (isprint(ch)) { - out << " = '" << (char)ch << "'\n"; - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TextFont::find_character_gsets -// Access: Private -// Description: Given that 'root' is a Node containing at least a -// polygon and a point which define the character's -// appearance and kern position, respectively, -// recursively walk the hierarchy and root and locate -// those two Geoms. -//////////////////////////////////////////////////////////////////// -bool TextFont:: -find_character_gsets(Node *root, Geom *&ch, GeomPoint *&dot, - AllTransitionsWrapper &trans) { - if (root->is_of_type(GeomNode::get_class_type())) { - GeomNode *geode = (GeomNode *)root; - - bool found = false; - for (int i = 0; i < geode->get_num_geoms(); i++) { - dDrawable *geom = geode->get_geom(i); - if (geom->is_of_type(GeomPoint::get_class_type())) { - dot = DCAST(GeomPoint, geom); - - } else if (geom->is_of_type(Geom::get_class_type())) { - ch = DCAST(Geom, geom); - found = true; - } - } - return found; - - } else { - TypeHandle graph_type = RenderRelation::get_class_type(); - int num_children = root->get_num_children(graph_type); - for (int i = 0; i < num_children; i++) { - NodeRelation *child_arc = root->get_child(graph_type, i); - if (find_character_gsets(child_arc->get_child(), ch, dot, trans)) { - trans.extract_from(child_arc); - } - } - return false; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TextFont::find_characters -// Access: Private -// Description: Walk the hierarchy beginning at the indicated root -// and locate any nodes whose names are just integers. -// These are taken to be characters, and their -// definitions and kern informations are retrieved. -//////////////////////////////////////////////////////////////////// -void TextFont:: -find_characters(Node *root) { - string name; - if (root->is_of_type(NamedNode::get_class_type())) { - name = DCAST(NamedNode, root)->get_name(); - } - - bool all_digits = !name.empty(); - const char *p = name.c_str(); - while (all_digits && *p != '\0') { - // VC++ complains if we treat an int as a bool, so we have to do - // this != 0 comparsion on the int isdigit() function to shut it - // up. - all_digits = (isdigit(*p) != 0); - p++; - } - - if (all_digits) { - int character = atoi(name.c_str()); - Geom *ch = NULL; - GeomPoint *dot = NULL; - AllTransitionsWrapper trans; - find_character_gsets(root, ch, dot, trans); - if (dot != NULL) { - // Get the first vertex from the "dot" geoset. This will be the - // origin of the next character. - PTA_Vertexf alist; - PTA_ushort ilist; - float width; - dot->get_coords(alist, ilist); - if (ilist.empty()) { - width = alist[0][0]; - } else { - width = alist[ilist[0]][0]; - } - - _defs[character] = CharDef(ch, width, trans); - } - - } else if (name == "ds") { - // The group "ds" is a special node that indicate's the font's - // design size, or line height. - - Geom *ch = NULL; - GeomPoint *dot = NULL; - AllTransitionsWrapper trans; - find_character_gsets(root, ch, dot, trans); - if (dot != NULL) { - // Get the first vertex from the "dot" geoset. This will be the - // design size indicator. - PTA_Vertexf alist; - PTA_ushort ilist; - dot->get_coords(alist, ilist); - if (ilist.empty()) { - _font_height = alist[0][2]; - } else { - _font_height = alist[ilist[0]][2]; - } - } - - } else { - TypeHandle graph_type = RenderRelation::get_class_type(); - int num_children = root->get_num_children(graph_type); - for (int i = 0; i < num_children; i++) { - NodeRelation *child_arc = root->get_child(graph_type, i); - find_characters(child_arc->get_child()); - } - } + << "TextFont " << get_name() << "\n"; } diff --git a/panda/src/text/textFont.h b/panda/src/text/textFont.h index a5bf57c528..b08eb22626 100644 --- a/panda/src/text/textFont.h +++ b/panda/src/text/textFont.h @@ -1,5 +1,5 @@ // Filename: textFont.h -// Created by: drose (03May01) +// Created by: drose (08Feb02) // //////////////////////////////////////////////////////////////////// // @@ -19,61 +19,47 @@ #ifndef TEXTFONT_H #define TEXTFONT_H -#include +#include "pandabase.h" #include "config_text.h" - -#include -#include -#include -#include - +#include "typedReferenceCount.h" +#include "namable.h" #include "pmap.h" class Node; -class Geom; -class GeomPoint; +class TextGlyph; //////////////////////////////////////////////////////////////////// // Class : TextFont -// Description : +// Description : An encapsulation of a font; i.e. a set of glyphs that +// may be assembled together by a TextNode to represent +// a string of text. +// +// This is just an abstract interface; see +// StaticTextFont or DynamicTextFont for an actual +// implementation. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA TextFont : public TypedReferenceCount, public Namable { +public: + TextFont(); + PUBLISHED: - TextFont(Node *font_def); - ~TextFont(); + virtual ~TextFont(); INLINE float get_line_height() const; - float calc_width(char ch) const; + float calc_width(int ch) const; float calc_width(const string &line) const; string wordwrap_to(const string &text, float wordwrap_width, bool preserve_trailing_whitespace) const; - void write(ostream &out, int indent_level) const; + virtual void write(ostream &out, int indent_level) const; -private: - // Private interfaces for the benefit of TextNode. - class CharDef { - public: - CharDef() { } - CharDef(Geom *geom, float width, const AllTransitionsWrapper &trans); - Geom *_geom; - float _width; - AllTransitionsWrapper _trans; - }; +public: + virtual const TextGlyph *get_glyph(int character) const=0; - INLINE const CharDef *get_char(int character) const; - -private: - bool find_character_gsets(Node *root, Geom *&ch, GeomPoint *&dot, - AllTransitionsWrapper &trans); - void find_characters(Node *root); - - typedef pmap CharDefs; - CharDefs _defs; - float _font_height; - PT_Node _font; +protected: + float _line_height; public: static TypeHandle get_class_type() { @@ -91,8 +77,6 @@ public: private: static TypeHandle _type_handle; - - friend class TextNode; }; #include "textFont.I" diff --git a/panda/src/text/textGlyph.I b/panda/src/text/textGlyph.I new file mode 100644 index 0000000000..14b4f61a43 --- /dev/null +++ b/panda/src/text/textGlyph.I @@ -0,0 +1,97 @@ +// Filename: textGlyph.I +// Created by: drose (08Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: TextGlyph::Default constructor +// Access: Public +// Description: This constructor makes an invalid glyph. +//////////////////////////////////////////////////////////////////// +INLINE TextGlyph:: +TextGlyph() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TextGlyph:: +TextGlyph(Geom *geom, const AllTransitionsWrapper &trans, float advance) : + _geom(geom), _trans(trans), _advance(advance) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TextGlyph:: +TextGlyph(const TextGlyph ©) : + _geom(copy._geom), + _trans(copy._trans), + _advance(copy._advance) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void TextGlyph:: +operator = (const TextGlyph ©) { + _geom = copy._geom; + _trans = copy._trans; + _advance = copy._advance; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::get_geom +// Access: Public +// Description: Returns a Geom that renders the particular glyph. +//////////////////////////////////////////////////////////////////// +INLINE Geom *TextGlyph:: +get_geom() const { + return _geom; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::get_trans +// Access: Public +// Description: Returns the state transitions that should be applied +// to the glyph geometry to render it correctly. +//////////////////////////////////////////////////////////////////// +INLINE const AllTransitionsWrapper &TextGlyph:: +get_trans() const { + return _trans; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::get_advance +// Access: Public +// Description: Returns the distance by which the character pointer +// should be advanced after placing this character; +// i.e. the approximate width the character takes up on +// the line. +//////////////////////////////////////////////////////////////////// +INLINE float TextGlyph:: +get_advance() const { + return _advance; +} diff --git a/panda/src/text/textGlyph.cxx b/panda/src/text/textGlyph.cxx new file mode 100644 index 0000000000..4fc3d8568a --- /dev/null +++ b/panda/src/text/textGlyph.cxx @@ -0,0 +1,19 @@ +// Filename: textGlyph.cxx +// Created by: drose (08Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "textGlyph.h" diff --git a/panda/src/text/textGlyph.h b/panda/src/text/textGlyph.h new file mode 100644 index 0000000000..2db7adf746 --- /dev/null +++ b/panda/src/text/textGlyph.h @@ -0,0 +1,53 @@ +// Filename: textGlyph.h +// Created by: drose (08Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 TEXTGLYPH_H +#define TEXTGLYPH_H + +#include "pandabase.h" +#include "allTransitionsWrapper.h" + +class Geom; +class TextGlyph; + +//////////////////////////////////////////////////////////////////// +// Class : TextGlyph +// Description : A representation of a single glyph (character) from a +// font. This is a piece of renderable geometry of some +// kind. +//////////////////////////////////////////////////////////////////// +class TextGlyph { +public: + INLINE TextGlyph(); + INLINE TextGlyph(Geom *geom, const AllTransitionsWrapper &trans, float advance); + INLINE TextGlyph(const TextGlyph ©); + INLINE void operator = (const TextGlyph ©); + + INLINE Geom *get_geom() const; + INLINE const AllTransitionsWrapper &get_trans() const; + INLINE float get_advance() const; + +private: + Geom *_geom; + AllTransitionsWrapper _trans; + float _advance; +}; + +#include "textGlyph.I" + +#endif diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 839f76271a..ef315a34c6 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -16,6 +16,7 @@ // //////////////////////////////////////////////////////////////////// #include "textNode.h" +#include "textGlyph.h" #include "config_text.h" #include "compose_matrix.h" @@ -447,12 +448,12 @@ assemble_row(const char *&source, Node *dest) { } else { // A printable character. - const TextFont::CharDef *def = _font->get_char(character); - if (def == (const TextFont::CharDef *)NULL) { + const TextGlyph *glyph = _font->get_glyph(character); + if (glyph == (const TextGlyph *)NULL) { text_cat.warning() << "No definition in " << _font->get_name() << " for character " << character; - if (isprint(character)) { + if (character < 128 && isprint(character)) { text_cat.warning(false) << " ('" << (char)character << "')"; } @@ -460,9 +461,9 @@ assemble_row(const char *&source, Node *dest) { << "\n"; } else { - Geom *char_geom = def->_geom; - float char_width = def->_width; - const AllTransitionsWrapper &trans = def->_trans; + Geom *char_geom = glyph->get_geom(); + float char_advance = glyph->get_advance(); + const AllTransitionsWrapper &trans = glyph->get_trans(); LMatrix4f mat = LMatrix4f::ident_mat(); mat.set_row(3, LVector3f(xpos, 0.0f, 0.0f)); @@ -475,7 +476,7 @@ assemble_row(const char *&source, Node *dest) { trans.store_to(rel); } - xpos += char_width; + xpos += char_advance; } } source++; @@ -575,10 +576,10 @@ measure_row(const char *&source) { } else { // A printable character. - const TextFont::CharDef *def = _font->get_char(character); - if (def != (const TextFont::CharDef *)NULL) { - float char_width = def->_width; - xpos += char_width; + const TextGlyph *glyph = _font->get_glyph(character); + if (glyph != (const TextGlyph *)NULL) { + float char_advance = glyph->get_advance(); + xpos += char_advance; } } source++; diff --git a/panda/src/text/text_composite1.cxx b/panda/src/text/text_composite1.cxx index 18026f1d80..47c8e4dbbf 100644 --- a/panda/src/text/text_composite1.cxx +++ b/panda/src/text/text_composite1.cxx @@ -1,2 +1,4 @@ #include "config_text.cxx" +#include "staticTextFont.cxx" #include "textFont.cxx" +#include "textGlyph.cxx"