From 8e63f99ee2172ecc63c4bf1e7b1dbda5ab7d647d Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 30 Jan 2003 18:48:47 +0000 Subject: [PATCH] support for explicit decoding/encoding of wide characters at the python level --- panda/src/text/textNode.I | 99 ++++++++++++++++++++++++++++++++++--- panda/src/text/textNode.cxx | 24 ++++----- panda/src/text/textNode.h | 7 +++ 3 files changed, 112 insertions(+), 18 deletions(-) diff --git a/panda/src/text/textNode.I b/panda/src/text/textNode.I index 66bccf5547..4f45a624d5 100644 --- a/panda/src/text/textNode.I +++ b/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 diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index cd02b90a3d..38c483aa03 100644 --- a/panda/src/text/textNode.cxx +++ b/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); } diff --git a/panda/src/text/textNode.h b/panda/src/text/textNode.h index 5bd4e71ebf..edc3940bda 100644 --- a/panda/src/text/textNode.h +++ b/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;