Browse Source

support for explicit decoding/encoding of wide characters at the python level

David Rose 23 years ago
parent
commit
8e63f99ee2
3 changed files with 112 additions and 18 deletions
  1. 92 7
      panda/src/text/textNode.I
  2. 13 11
      panda/src/text/textNode.cxx
  3. 7 0
      panda/src/text/textNode.h

+ 92 - 7
panda/src/text/textNode.I

@@ -124,6 +124,9 @@ get_font() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void TextNode::
 set_encoding(TextNode::Encoding encoding) {
+  // Force the previously-set strings to be encoded or decoded now.
+  get_text();
+  get_wtext();
   _encoding = encoding;
 }
 
@@ -1031,7 +1034,7 @@ get_coordinate_system() const {
 INLINE void TextNode::
 set_text(const string &text) {
   _text = text;
-  _wtext = decode_text(text);
+  _flags = (_flags | F_got_text) & ~F_got_wtext;
   rebuild(true);
 }
 
@@ -1042,7 +1045,9 @@ set_text(const string &text) {
 ////////////////////////////////////////////////////////////////////
 INLINE void TextNode::
 clear_text() {
-  _text = "";
+  _text = string();
+  _wtext = wstring();
+  _flags |= (F_got_text | F_got_wtext);
   rebuild(true);
 }
 
@@ -1053,7 +1058,11 @@ clear_text() {
 ////////////////////////////////////////////////////////////////////
 INLINE bool TextNode::
 has_text() const {
-  return !_text.empty();
+  if (_flags & F_got_wtext) {
+    return !_wtext.empty();
+  } else {
+    return !_text.empty();
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1063,14 +1072,73 @@ has_text() const {
 ////////////////////////////////////////////////////////////////////
 INLINE string TextNode::
 get_text() const {
+  if ((_flags & F_got_text) == 0) {
+    ((TextNode *)this)->_text = encode_wtext(_wtext);
+    ((TextNode *)this)->_flags |= F_got_text;
+  }
   return _text;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::append_text
+//       Access: Published
+//  Description: Appends the indicates string to the end of the stored
+//               text.
+////////////////////////////////////////////////////////////////////
+INLINE void TextNode::
+append_text(const string &text) {
+  _text = get_text() + text;
+  _flags = (_flags | F_got_text) & ~F_got_wtext;
+  rebuild(true);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::append_char
+//       Access: Published
+//  Description: Appends a single character to the end of the stored
+//               text.  This may be a wide character, up to 16 bits in
+//               Unicode.
+////////////////////////////////////////////////////////////////////
+INLINE void TextNode::
+append_char(int character) {
+  _wtext = get_wtext() + wstring(1, (wchar_t)character);
+  _flags = (_flags | F_got_wtext) & ~F_got_text;
+  rebuild(true);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::get_num_chars
+//       Access: Published
+//  Description: Returns the number of characters in the stored text.
+//               This is a count of wide characters, after the string
+//               has been decoded according to set_encoding().
+////////////////////////////////////////////////////////////////////
+INLINE int TextNode::
+get_num_chars() const {
+  return get_wtext().length();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::get_char
+//       Access: Published
+//  Description: Returns the Unicode value of the nth character in the
+//               stored text.  This may be a wide character (greater
+//               than 255), after the string has been decoded
+//               according to set_encoding().
+////////////////////////////////////////////////////////////////////
+INLINE int TextNode::
+get_char(int index) const {
+  get_wtext();
+  nassertr(index >= 0 && index < (int)_wtext.length(), 0);
+  return _wtext[index];
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::calc_width
 //       Access: Published
 //  Description: Returns the width of a single character of the font,
-//               or 0.0 if the character is not known.
+//               or 0.0 if the character is not known.  This may be a
+//               wide character (greater than 255).
 ////////////////////////////////////////////////////////////////////
 INLINE float TextNode::
 calc_width(int character) const {
@@ -1250,7 +1318,7 @@ get_num_rows() const {
 INLINE void TextNode::
 set_wtext(const wstring &wtext) {
   _wtext = wtext;
-  _text = encode_wtext(wtext);
+  _flags = (_flags | F_got_wtext) & ~F_got_text;
   rebuild(true);
 }
 
@@ -1262,12 +1330,29 @@ set_wtext(const wstring &wtext) {
 ////////////////////////////////////////////////////////////////////
 INLINE const wstring &TextNode::
 get_wtext() const {
+  if ((_flags & F_got_wtext) == 0) {
+    ((TextNode *)this)->_wtext = decode_text(_text);
+    ((TextNode *)this)->_flags |= F_got_wtext;
+  }
   return _wtext;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::append_wtext
+//       Access: Public
+//  Description: Appends the indicates string to the end of the stored
+//               wide-character text.
+////////////////////////////////////////////////////////////////////
+INLINE void TextNode::
+append_wtext(const wstring &wtext) {
+  _wtext = get_wtext() + wtext;
+  _flags = (_flags | F_got_wtext) & ~F_got_text;
+  rebuild(true);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::calc_width
-//       Access: Published
+//       Access: Public
 //  Description: Returns the width of a line of text of arbitrary
 //               characters.  The line should not include the newline
 //               character.
@@ -1280,7 +1365,7 @@ calc_width(const wstring &line) const {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::wordwrap_to
-//       Access: Published
+//       Access: Public
 //  Description: Inserts newlines into the given text at the
 //               appropriate places in order to make each line be the
 //               longest possible line that is not longer than

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

@@ -52,8 +52,11 @@ TextNode::
 TextNode(const string &name) : PandaNode(name) {
   _encoding = _default_encoding;
   _slant = 0.0f;
-
-  _flags = 0;
+  
+  // Initially, since the text string is empty, we know that both
+  // _text and _wtext accurately reflect the empty state; so we "got"
+  // both of them.
+  _flags = (F_got_text | F_got_wtext);
   _align = A_left;
   _wordwrap_width = 1.0f;
 
@@ -213,7 +216,7 @@ write(ostream &out, int indent_level) const {
     << "in coordinate system " << _coordinate_system << "\n";
 
   indent(out, indent_level + 2)
-    << "\ntext is " << _text << "\n";
+    << "\ntext is " << get_text() << "\n";
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -227,7 +230,7 @@ PT(PandaNode) TextNode::
 generate() {
   if (text_cat.is_debug()) {
     text_cat.debug()
-      << "Rebuilding " << *this << " with '" << _text << "'\n";
+      << "Rebuilding " << *this << " with '" << get_text() << "'\n";
   }
 
   // The strategy here will be to assemble together a bunch of
@@ -247,9 +250,9 @@ generate() {
   _num_rows = 0;
 
   // Now build a new sub-tree for all the text components.
-  PT(PandaNode) root = new PandaNode(_text);
+  PT(PandaNode) root = new PandaNode(get_text());
 
-  if (_text.empty() || _font.is_null()) {
+  if (!has_text() || _font.is_null()) {
     return root;
   }
 
@@ -262,7 +265,7 @@ generate() {
 
   root->set_transform(TransformState::make_mat(mat));
 
-  wstring wtext = _wtext;
+  wstring wtext = get_wtext();
   if (has_wordwrap()) {
     wtext = _font->wordwrap_to(wtext, _wordwrap_width, false);
   }
@@ -474,8 +477,7 @@ xform(const LMatrix4f &mat) {
 //     Function: TextNode::decode_text_impl
 //       Access: Private
 //  Description: Decodes the eight-bit stream from the indicated
-//               decoder, storing the decoded unicode characters in
-//               _wtext.
+//               decoder, returning the decoded wide-char string.
 ////////////////////////////////////////////////////////////////////
 wstring TextNode::
 decode_text_impl(StringDecoder &decoder) const {
@@ -629,11 +631,11 @@ do_measure() {
   _lr3d.set(0.0f, 0.0f, 0.0f);
   _num_rows = 0;
 
-  if (_text.empty() || _font.is_null()) {
+  if (!has_text() || _font.is_null()) {
     return;
   }
 
-  wstring wtext = _wtext;
+  wstring wtext = get_wtext();
   if (has_wordwrap()) {
     wtext = _font->wordwrap_to(wtext, _wordwrap_width, false);
   }

+ 7 - 0
panda/src/text/textNode.h

@@ -176,6 +176,10 @@ PUBLISHED:
   INLINE void clear_text();
   INLINE bool has_text() const;
   INLINE string get_text() const;
+  INLINE void append_text(const string &text);
+  INLINE void append_char(int character);
+  INLINE int get_num_chars() const;
+  INLINE int get_char(int index) const;
 
   INLINE float calc_width(int character) const;
   INLINE float calc_width(const string &line) const;
@@ -207,6 +211,7 @@ public:
   // Direct support for wide-character strings.
   INLINE void set_wtext(const wstring &wtext);
   INLINE const wstring &get_wtext() const;
+  INLINE void append_wtext(const wstring &text);
 
   INLINE float calc_width(const wstring &line) const;
   INLINE wstring wordwrap_to(const wstring &wtext, float wordwrap_width,
@@ -264,6 +269,8 @@ private:
     F_card_transp      =  0x0200,
     F_has_card_border  =  0x0400,
     F_expand_amp       =  0x0800,
+    F_got_text         =  0x1000,
+    F_got_wtext        =  0x2000,
   };
 
   int _flags;