Browse Source

split TextFont into TextFont and StaticTextFont, preparing for DynamicTextFont

David Rose 24 years ago
parent
commit
00e38798ef

+ 5 - 1
direct/src/showbase/Loader.py

@@ -108,7 +108,11 @@ class Loader:
         nodePath = hidden.attachNewNode(node)
         nodePath = hidden.attachNewNode(node)
         nodePath.adjustAllPriorities(priority)
         nodePath.adjustAllPriorities(priority)
         # Now create text font from the node
         # 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
         # And remove node path
         nodePath.removeNode()
         nodePath.removeNode()
         return font
         return font

+ 11 - 3
panda/src/text/Sources.pp

@@ -10,13 +10,21 @@
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx 
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx 
 
 
   #define SOURCES \
   #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
     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 \
   #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
   #define IGATESCAN all
 
 

+ 2 - 0
panda/src/text/config_text.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "config_text.h"
 #include "config_text.h"
+#include "staticTextFont.h"
 #include "textFont.h"
 #include "textFont.h"
 #include "textNode.h"
 #include "textNode.h"
 
 
@@ -26,6 +27,7 @@ Configure(config_text);
 NotifyCategoryDef(text, "");
 NotifyCategoryDef(text, "");
 
 
 ConfigureFn(config_text) {
 ConfigureFn(config_text) {
+  StaticTextFont::init_type();
   TextFont::init_type();
   TextFont::init_type();
   TextNode::init_type();
   TextNode::init_type();
 }
 }

+ 18 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+

+ 297 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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());
+    }
+  }
+}

+ 89 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef STATICTEXTFONT_H
+#define STATICTEXTFONT_H
+
+#include <pandabase.h>
+
+#include "config_text.h"
+#include "textFont.h"
+#include "textGlyph.h"
+
+#include <typedReferenceCount.h>
+#include <namable.h>
+#include <pt_Node.h>
+#include <allTransitionsWrapper.h>
+
+#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<int, TextGlyph> 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

+ 3 - 20
panda/src/text/textFont.I

@@ -1,5 +1,5 @@
 // Filename: textFont.I
 // Filename: textFont.I
-// Created by:  drose (03May01)
+// Created by:  drose (08Feb02)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -21,26 +21,9 @@
 //     Function: TextFont::get_line_height
 //     Function: TextFont::get_line_height
 //       Access: Published
 //       Access: Published
 //  Description: Returns the number of units high each line of text
 //  Description: Returns the number of units high each line of text
-//               is.  This is based on the font.
+//               is.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE float TextFont::
 INLINE float TextFont::
 get_line_height() const {
 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;
 }
 }

+ 13 - 251
panda/src/text/textFont.cxx

@@ -1,5 +1,5 @@
 // Filename: textFont.cxx
 // Filename: textFont.cxx
-// Created by:  drose (03May01)
+// Created by:  drose (08Feb02)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -18,17 +18,11 @@
 
 
 #include "textFont.h"
 #include "textFont.h"
 #include "config_text.h"
 #include "config_text.h"
-
-#include "geom.h"
-#include "geomPoint.h"
-#include "geomNode.h"
-#include "namedNode.h"
-#include "renderRelation.h"
-
 #include "ctype.h"
 #include "ctype.h"
 
 
 TypeHandle TextFont::_type_handle;
 TypeHandle TextFont::_type_handle;
 
 
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: isblank
 //     Function: isblank
 //  Description: An internal function, similar to isspace(), except it
 //  Description: An internal function, similar to isspace(), except it
@@ -39,40 +33,19 @@ isblank(char ch) {
   return (ch == ' ' || ch == '\t');
   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
 //     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::
-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
 //     Function: TextFont::Destructor
-//       Access: Published
+//       Access: Published, Virtual
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 TextFont::
 TextFont::
@@ -86,19 +59,19 @@ TextFont::
 //               or 0.0 if the character is not known.
 //               or 0.0 if the character is not known.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 float TextFont::
 float TextFont::
-calc_width(char ch) const {
+calc_width(int ch) const {
   if (ch == ' ') {
   if (ch == ' ') {
     // A space is a special case.
     // A space is a special case.
     return 0.25;
     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.
     // Unknown character.
     return 0.0;
     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;
   return output_text;
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextFont::write
 //     Function: TextFont::write
-//       Access: Published
+//       Access: Published, Virtual
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TextFont::
 void TextFont::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {
   indent(out, indent_level)
   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";
 }
 }

+ 22 - 38
panda/src/text/textFont.h

@@ -1,5 +1,5 @@
 // Filename: textFont.h
 // Filename: textFont.h
-// Created by:  drose (03May01)
+// Created by:  drose (08Feb02)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -19,61 +19,47 @@
 #ifndef TEXTFONT_H
 #ifndef TEXTFONT_H
 #define TEXTFONT_H
 #define TEXTFONT_H
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
 #include "config_text.h"
 #include "config_text.h"
-
-#include <typedReferenceCount.h>
-#include <namable.h>
-#include <pt_Node.h>
-#include <allTransitionsWrapper.h>
-
+#include "typedReferenceCount.h"
+#include "namable.h"
 #include "pmap.h"
 #include "pmap.h"
 
 
 class Node;
 class Node;
-class Geom;
-class GeomPoint;
+class TextGlyph;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : TextFont
 //       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 {
 class EXPCL_PANDA TextFont : public TypedReferenceCount, public Namable {
+public:
+  TextFont();
+
 PUBLISHED:
 PUBLISHED:
-  TextFont(Node *font_def);
-  ~TextFont();
+  virtual ~TextFont();
 
 
   INLINE float get_line_height() const;
   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;
   float calc_width(const string &line) const;
   string wordwrap_to(const string &text, float wordwrap_width,
   string wordwrap_to(const string &text, float wordwrap_width,
                      bool preserve_trailing_whitespace) const;
                      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;
-  };
-
-  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);
+public:
+  virtual const TextGlyph *get_glyph(int character) const=0;
 
 
-  typedef pmap<int, CharDef> CharDefs;
-  CharDefs _defs;
-  float _font_height;
-  PT_Node _font;
+protected:
+  float _line_height;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
@@ -91,8 +77,6 @@ public:
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
-
-  friend class TextNode;
 };
 };
 
 
 #include "textFont.I"
 #include "textFont.I"

+ 97 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     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 &copy) :
+  _geom(copy._geom),
+  _trans(copy._trans),
+  _advance(copy._advance) 
+{ 
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextGlyph::Copy Assignment Operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void TextGlyph::
+operator = (const TextGlyph &copy) {
+  _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;
+}

+ 19 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "textGlyph.h"

+ 53 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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 &copy);
+  INLINE void operator = (const TextGlyph &copy);
+
+  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

+ 12 - 11
panda/src/text/textNode.cxx

@@ -16,6 +16,7 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 #include "textNode.h"
 #include "textNode.h"
+#include "textGlyph.h"
 #include "config_text.h"
 #include "config_text.h"
 
 
 #include "compose_matrix.h"
 #include "compose_matrix.h"
@@ -447,12 +448,12 @@ assemble_row(const char *&source, Node *dest) {
     } else {
     } else {
       // A printable character.
       // 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()
         text_cat.warning()
           << "No definition in " << _font->get_name() 
           << "No definition in " << _font->get_name() 
           << " for character " << character;
           << " for character " << character;
-        if (isprint(character)) {
+        if (character < 128 && isprint(character)) {
           text_cat.warning(false)
           text_cat.warning(false)
             << " ('" << (char)character << "')";
             << " ('" << (char)character << "')";
         }
         }
@@ -460,9 +461,9 @@ assemble_row(const char *&source, Node *dest) {
           << "\n";
           << "\n";
 
 
       } else {
       } 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();
         LMatrix4f mat = LMatrix4f::ident_mat();
         mat.set_row(3, LVector3f(xpos, 0.0f, 0.0f));
         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);
           trans.store_to(rel);
         }
         }
 
 
-        xpos += char_width;
+        xpos += char_advance;
       }
       }
     }
     }
     source++;
     source++;
@@ -575,10 +576,10 @@ measure_row(const char *&source) {
     } else {
     } else {
       // A printable character.
       // 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++;
     source++;

+ 2 - 0
panda/src/text/text_composite1.cxx

@@ -1,2 +1,4 @@
 #include "config_text.cxx"
 #include "config_text.cxx"
+#include "staticTextFont.cxx"
 #include "textFont.cxx"
 #include "textFont.cxx"
+#include "textGlyph.cxx"