mo' better unicode

This commit is contained in:
David Rose 2002-02-16 02:25:10 +00:00
parent 0f60ab4d9a
commit 33042973b5
4 changed files with 126 additions and 37 deletions

View File

@ -40,6 +40,18 @@ ConfigureFn(config_text) {
GeomTextGlyph::init_type(); GeomTextGlyph::init_type();
GeomTextGlyph::register_with_read_factory(); GeomTextGlyph::register_with_read_factory();
#endif #endif
string text_encoding = config_text.GetString("text-encoding", "iso8859");
if (text_encoding == "iso8859") {
TextNode::_default_encoding = TextNode::E_iso8859;
} else if (text_encoding == "utf8") {
TextNode::_default_encoding = TextNode::E_utf8;
} else if (text_encoding == "unicode") {
TextNode::_default_encoding = TextNode::E_unicode;
} else {
text_cat.error()
<< "Invalid text-encoding: " << text_encoding << "\n";
}
} }
const bool text_flatten = config_text.GetBool("text-flatten", true); const bool text_flatten = config_text.GetBool("text-flatten", true);

View File

@ -1060,9 +1060,9 @@ get_text() const {
// or 0.0 if the character is not known. // or 0.0 if the character is not known.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE float TextNode:: INLINE float TextNode::
calc_width(char ch) const { calc_width(int character) const {
nassertr(_font != (TextFont *)NULL, 0.0); nassertr(_font != (TextFont *)NULL, 0.0);
return _font->calc_width(ch); return _font->calc_width(character);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -1075,7 +1075,7 @@ calc_width(char ch) const {
INLINE float TextNode:: INLINE float TextNode::
calc_width(const string &line) const { calc_width(const string &line) const {
nassertr(_font != (TextFont *)NULL, 0.0); nassertr(_font != (TextFont *)NULL, 0.0);
return _font->calc_width(line); return _font->calc_width(decode_text(line));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -1091,7 +1091,7 @@ INLINE string TextNode::
wordwrap_to(const string &text, float wordwrap_width, wordwrap_to(const string &text, float wordwrap_width,
bool preserve_trailing_whitespace) const { bool preserve_trailing_whitespace) const {
nassertr(_font != (TextFont *)NULL, text); nassertr(_font != (TextFont *)NULL, text);
return _font->wordwrap_to(text, wordwrap_width, preserve_trailing_whitespace); return encode_wtext(_font->wordwrap_to(decode_text(text), wordwrap_width, preserve_trailing_whitespace));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -39,6 +39,8 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
TypeHandle TextNode::_type_handle; TypeHandle TextNode::_type_handle;
TextNode::Encoding TextNode::_default_encoding;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TextNode::Constructor // Function: TextNode::Constructor
// Access: Published // Access: Published
@ -46,7 +48,7 @@ TypeHandle TextNode::_type_handle;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
TextNode:: TextNode::
TextNode(const string &name) : NamedNode(name) { TextNode(const string &name) : NamedNode(name) {
_encoding = E_iso8859; _encoding = _default_encoding;
_slant = 0.0f; _slant = 0.0f;
_flags = 0; _flags = 0;
@ -99,29 +101,7 @@ TextNode::
void TextNode:: void TextNode::
set_text(const string &text) { set_text(const string &text) {
_text = text; _text = text;
switch (_encoding) { _wtext = decode_text(text);
case E_utf8:
{
StringUtf8Decoder decoder(_text);
decode_wtext(decoder);
}
break;
case E_unicode:
{
StringUnicodeDecoder decoder(_text);
decode_wtext(decoder);
}
break;
case E_iso8859:
default:
{
StringDecoder decoder(_text);
decode_wtext(decoder);
}
};
rebuild(true); rebuild(true);
} }
@ -394,15 +374,102 @@ generate() {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TextNode::decode_wtext // Function: TextNode::encode_wchar
// Access: Public
// Description: Encodes a single wide char into a one-, two-, or
// three-byte string, according to the current encoding
// system in effect.
////////////////////////////////////////////////////////////////////
string TextNode::
encode_wchar(wchar_t ch) const {
switch (_encoding) {
case E_iso8859:
if (isascii(ch)) {
return string(1, (char)ch);
} else {
return ".";
}
case E_utf8:
if (ch < 0x80) {
return string(1, (char)ch);
} else if (ch < 0x800) {
return
string(1, (char)(ch >> 6) | 0xc0) +
string(1, (char)(ch & 0x3f) | 0x80);
} else {
return
string(1, (char)(ch >> 12) | 0xe0) +
string(1, (char)((ch >> 6) & 0x3f) | 0x80) +
string(1, (char)(ch & 0x3f) | 0x80);
}
case E_unicode:
return
string(1, (char)(ch >> 8)) +
string(1, (char)(ch & 0xff));
}
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::encode_wtext
// Access: Public
// Description: Encodes a wide-text string into a single-char string,
// accoding to the current encoding.
////////////////////////////////////////////////////////////////////
string TextNode::
encode_wtext(const wstring &text) const {
string result;
for (wstring::const_iterator pi = text.begin(); pi != text.end(); ++pi) {
result += encode_wchar(*pi);
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::decode_text
// Access: Public
// Description: Returns the given wstring decoded to a single-byte
// string, via the current encoding system.
////////////////////////////////////////////////////////////////////
wstring TextNode::
decode_text(const string &text) const {
switch (_encoding) {
case E_utf8:
{
StringUtf8Decoder decoder(text);
return decode_text_impl(decoder);
}
break;
case E_unicode:
{
StringUnicodeDecoder decoder(text);
return decode_text_impl(decoder);
}
break;
case E_iso8859:
default:
{
StringDecoder decoder(text);
return decode_text_impl(decoder);
}
};
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::decode_text_impl
// Access: Private // Access: Private
// Description: Decodes the eight-bit stream from the indicated // Description: Decodes the eight-bit stream from the indicated
// decoder, storing the decoded unicode characters in // decoder, storing the decoded unicode characters in
// _wtext. // _wtext.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void TextNode:: wstring TextNode::
decode_wtext(StringDecoder &decoder) { decode_text_impl(StringDecoder &decoder) const {
_wtext.erase(_wtext.begin(), _wtext.end()); wstring result;
bool expand_amp = get_expand_amp(); bool expand_amp = get_expand_amp();
wchar_t character = decoder.get_next_character(); wchar_t character = decoder.get_next_character();
@ -412,9 +479,11 @@ decode_wtext(StringDecoder &decoder) {
// character. // character.
character = expand_amp_sequence(decoder); character = expand_amp_sequence(decoder);
} }
_wtext += character; result += character;
character = decoder.get_next_character(); character = decoder.get_next_character();
} }
return result;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -427,7 +496,7 @@ decode_wtext(StringDecoder &decoder) {
// character, do the expansion and return the character. // character, do the expansion and return the character.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int TextNode:: int TextNode::
expand_amp_sequence(StringDecoder &decoder) { expand_amp_sequence(StringDecoder &decoder) const {
int result = 0; int result = 0;
int character = decoder.get_next_character(); int character = decoder.get_next_character();

View File

@ -191,7 +191,7 @@ PUBLISHED:
INLINE bool has_text() const; INLINE bool has_text() const;
INLINE string get_text() const; INLINE string get_text() const;
INLINE float calc_width(char ch) const; INLINE float calc_width(int character) const;
INLINE float calc_width(const string &line) const; INLINE float calc_width(const string &line) const;
INLINE string wordwrap_to(const string &text, float wordwrap_width, INLINE string wordwrap_to(const string &text, float wordwrap_width,
bool preserve_trailing_whitespace) const; bool preserve_trailing_whitespace) const;
@ -217,9 +217,14 @@ PUBLISHED:
PT_Node generate(); PT_Node generate();
public:
string encode_wchar(wchar_t ch) const;
string encode_wtext(const wstring &text) const;
wstring decode_text(const string &text) const;
private: private:
void decode_wtext(StringDecoder &decoder); wstring decode_text_impl(StringDecoder &decoder) const;
int expand_amp_sequence(StringDecoder &decoder); int expand_amp_sequence(StringDecoder &decoder) const;
void do_rebuild(); void do_rebuild();
void do_measure(); void do_measure();
@ -290,6 +295,9 @@ private:
int _freeze_level; int _freeze_level;
bool _needs_rebuild; bool _needs_rebuild;
public:
static Encoding _default_encoding;
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
return _type_handle; return _type_handle;