more control over encoding

This commit is contained in:
David Rose 2003-02-06 01:32:05 +00:00
parent 84cb559f00
commit 9aeeb1ce1a
3 changed files with 177 additions and 32 deletions

View File

@ -154,6 +154,7 @@ get_default_encoding() {
return _default_encoding;
}
/*
////////////////////////////////////////////////////////////////////
// Function: TextNode::set_expand_amp
// Access: Published
@ -185,6 +186,7 @@ INLINE bool TextNode::
get_expand_amp() const {
return (_flags & F_expand_amp) != 0;
}
*/
////////////////////////////////////////////////////////////////////
// Function: TextNode::get_line_height
@ -1129,6 +1131,21 @@ set_text(const string &text) {
}
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::set_text
// Access: Published
// Description: The two-parameter version of set_text() accepts an
// explicit encoding; the text is immediately decoded
// and stored as a wide-character string. Subsequent
// calls to get_text() will return the same text
// re-encoded using whichever encoding is specified by
// set_encoding().
////////////////////////////////////////////////////////////////////
INLINE void TextNode::
set_text(const string &text, TextNode::Encoding encoding) {
set_wtext(decode_text(text, encoding));
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::clear_text
// Access: Published
@ -1159,7 +1176,8 @@ has_text() const {
////////////////////////////////////////////////////////////////////
// Function: TextNode::get_text
// Access: Published
// Description:
// Description: Returns the current text, as encoded via the current
// encoding system.
////////////////////////////////////////////////////////////////////
INLINE string TextNode::
get_text() const {
@ -1170,6 +1188,17 @@ get_text() const {
return _text;
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::get_text
// Access: Published
// Description: Returns the current text, as encoded via the indicated
// encoding system.
////////////////////////////////////////////////////////////////////
INLINE string TextNode::
get_text(TextNode::Encoding encoding) const {
return encode_wtext(get_wtext(), encoding);
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::append_text
// Access: Published
@ -1184,14 +1213,14 @@ append_text(const string &text) {
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::append_char
// Function: TextNode::append_unicode_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) {
append_unicode_char(int character) {
_wtext = get_wtext() + wstring(1, (wchar_t)character);
_flags = (_flags | F_got_wtext) & ~F_got_text;
invalidate_with_measure();
@ -1210,7 +1239,7 @@ get_num_chars() const {
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::get_char
// Function: TextNode::get_unicode_char
// Access: Published
// Description: Returns the Unicode value of the nth character in the
// stored text. This may be a wide character (greater
@ -1218,12 +1247,35 @@ get_num_chars() const {
// according to set_encoding().
////////////////////////////////////////////////////////////////////
INLINE int TextNode::
get_char(int index) const {
get_unicode_char(int index) const {
get_wtext();
nassertr(index >= 0 && index < (int)_wtext.length(), 0);
return _wtext[index];
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::get_encoded_char
// Access: Published
// Description: Returns the nth char of the stored text, as a one-,
// two-, or three-byte encoded string.
////////////////////////////////////////////////////////////////////
INLINE string TextNode::
get_encoded_char(int index) const {
return get_encoded_char(index, get_encoding());
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::get_encoded_char
// Access: Published
// Description: Returns the nth char of the stored text, as a one-,
// two-, or three-byte encoded string.
////////////////////////////////////////////////////////////////////
INLINE string TextNode::
get_encoded_char(int index, TextNode::Encoding encoding) const {
wstring wch(1, (wchar_t)get_unicode_char(index));
return encode_wtext(wch, encoding);
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::get_text_as_ascii
// Access: Published
@ -1248,6 +1300,21 @@ get_text_as_ascii() const {
return encode_wtext(get_wtext_as_ascii());
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::reencode_text
// Access: Published, Static
// Description: Given the indicated text string, which is assumed to
// be encoded via the encoding "from", decodes it and
// then reencodes it into the encoding "to", and returns
// the newly encoded string. This does not change or
// affect any properties on the TextNode itself.
////////////////////////////////////////////////////////////////////
INLINE string TextNode::
reencode_text(const string &text, TextNode::Encoding from,
TextNode::Encoding to) {
return encode_wtext(decode_text(text, from), to);
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::calc_width
// Access: Published
@ -1491,6 +1558,28 @@ wordwrap_to(const wstring &wtext, float wordwrap_width,
return _font->wordwrap_to(wtext, wordwrap_width, preserve_trailing_whitespace);
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::encode_wtext
// Access: Public
// Description: Encodes a wide-text string into a single-char string,
// according to the current encoding.
////////////////////////////////////////////////////////////////////
INLINE string TextNode::
encode_wtext(const wstring &wtext) const {
return encode_wtext(wtext, _encoding);
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::decode_text
// Access: Public
// Description: Returns the given wstring decoded to a single-byte
// string, via the current encoding system.
////////////////////////////////////////////////////////////////////
INLINE wstring TextNode::
decode_text(const string &text) const {
return decode_text(text, _encoding);
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::invalidate_no_measure
// Access: Private

View File

@ -44,6 +44,8 @@
#include "cullTraverserData.h"
#include "geometricBoundingVolume.h"
#include "accumulatedAttribs.h"
#include "renderState.h"
#include "cullFaceAttrib.h"
#include "dcast.h"
#include <stdio.h>
@ -466,18 +468,34 @@ get_wtext_as_ascii() const {
////////////////////////////////////////////////////////////////////
// Function: TextNode::encode_wchar
// Access: Public
// Access: Public, Static
// Description: Encodes a single wide char into a one-, two-, or
// three-byte string, according to the current encoding
// system in effect.
// three-byte string, according to the given encoding
// system.
////////////////////////////////////////////////////////////////////
string TextNode::
encode_wchar(wchar_t ch) const {
switch (_encoding) {
encode_wchar(wchar_t ch, TextNode::Encoding encoding) {
switch (encoding) {
case E_iso8859:
if (isascii((unsigned int)ch)) {
if (ch < 0x100) {
return string(1, (char)ch);
} else {
// The character won't fit in the 8-bit ISO 8859. See if we can
// make it fit by reducing it to its ascii equivalent
// (essentially stripping off an unusual accent mark).
const UnicodeLatinMap::Entry *map_entry =
UnicodeLatinMap::look_up(ch);
if (map_entry != NULL && map_entry->_ascii_equiv != 0) {
// Yes, it has an ascii equivalent.
if (map_entry->_ascii_additional != 0) {
// In fact, it has two of them.
return
string(1, map_entry->_ascii_equiv) +
string(1, map_entry->_ascii_additional);
}
return string(1, map_entry->_ascii_equiv);
}
// Nope; return "." for lack of anything better.
return ".";
}
@ -506,16 +524,16 @@ encode_wchar(wchar_t ch) const {
////////////////////////////////////////////////////////////////////
// Function: TextNode::encode_wtext
// Access: Public
// Access: Public, Static
// Description: Encodes a wide-text string into a single-char string,
// accoding to the current encoding.
// according to the given encoding.
////////////////////////////////////////////////////////////////////
string TextNode::
encode_wtext(const wstring &wtext) const {
encode_wtext(const wstring &wtext, TextNode::Encoding encoding) {
string result;
for (wstring::const_iterator pi = wtext.begin(); pi != wtext.end(); ++pi) {
result += encode_wchar(*pi);
result += encode_wchar(*pi, encoding);
}
return result;
@ -523,13 +541,13 @@ encode_wtext(const wstring &wtext) const {
////////////////////////////////////////////////////////////////////
// Function: TextNode::decode_text
// Access: Public
// Access: Public, Static
// Description: Returns the given wstring decoded to a single-byte
// string, via the current encoding system.
// string, via the given encoding system.
////////////////////////////////////////////////////////////////////
wstring TextNode::
decode_text(const string &text) const {
switch (_encoding) {
decode_text(const string &text, TextNode::Encoding encoding) {
switch (encoding) {
case E_utf8:
{
StringUtf8Decoder decoder(text);
@ -762,22 +780,24 @@ recompute_internal_bound() {
////////////////////////////////////////////////////////////////////
// Function: TextNode::decode_text_impl
// Access: Private
// Access: Private, Static
// Description: Decodes the eight-bit stream from the indicated
// decoder, returning the decoded wide-char string.
////////////////////////////////////////////////////////////////////
wstring TextNode::
decode_text_impl(StringDecoder &decoder) const {
decode_text_impl(StringDecoder &decoder) {
wstring result;
bool expand_amp = get_expand_amp();
// bool expand_amp = get_expand_amp();
wchar_t character = decoder.get_next_character();
while (!decoder.is_eof()) {
/*
if (character == '&' && expand_amp) {
// An ampersand in expand_amp mode is treated as an escape
// character.
character = expand_amp_sequence(decoder);
}
*/
result += character;
character = decoder.get_next_character();
}
@ -785,6 +805,7 @@ decode_text_impl(StringDecoder &decoder) const {
return result;
}
/*
////////////////////////////////////////////////////////////////////
// Function: TextNode::expand_amp_sequence
// Access: Private
@ -832,7 +853,7 @@ expand_amp_sequence(StringDecoder &decoder) const {
int code;
} tokens[] = {
{ "amp", '&' }, { "lt", '<' }, { "gt", '>' }, { "quot", '"' },
{ "nbsp", ' ' /* 160 */ },
{ "nbsp", ' ' },
{ "iexcl", 161 }, { "cent", 162 }, { "pound", 163 }, { "curren", 164 },
{ "yen", 165 }, { "brvbar", 166 }, { "brkbar", 166 }, { "sect", 167 },
@ -873,6 +894,7 @@ expand_amp_sequence(StringDecoder &decoder) const {
// Some unrecognized sequence.
return 0;
}
*/
////////////////////////////////////////////////////////////////////
@ -1494,6 +1516,10 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
float t, u;
LMatrix4f accent_mat;
// This gets set to true if the glyph gets mirrored and needs
// to have backface culling disabled.
bool mirrored = false;
switch (transform) {
case CT_none:
accent_mat = LMatrix4f::ident_mat();
@ -1504,6 +1530,7 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
t = min_accent[0];
min_accent[0] = -max_accent[0];
max_accent[0] = -t;
mirrored = true;
break;
case CT_mirror_y:
@ -1511,6 +1538,7 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
t = min_accent[2];
min_accent[2] = -max_accent[2];
max_accent[2] = -t;
mirrored = true;
break;
case CT_rotate_90:
@ -1563,6 +1591,7 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
t = min_accent[2];
min_accent[2] = -max_accent[2] * squash_accent_scale_y;
max_accent[2] = -t * squash_accent_scale_y;
mirrored = true;
break;
case CT_squash_mirror_diag:
@ -1577,6 +1606,7 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
max_accent[0] = max_accent[2] * -squash_accent_scale_x;
min_accent[2] = -u * squash_accent_scale_y;
max_accent[2] = -t * squash_accent_scale_y;
mirrored = true;
break;
case CT_small_squash:
@ -1594,6 +1624,7 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
t = min_accent[2];
min_accent[2] = -max_accent[2] * small_squash_accent_scale_y;
max_accent[2] = -t * small_squash_accent_scale_y;
mirrored = true;
break;
case CT_small:
@ -1630,6 +1661,7 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
max_accent[0] = -t * tiny_accent_scale;
min_accent[2] *= tiny_accent_scale;
max_accent[2] *= tiny_accent_scale;
mirrored = true;
break;
case CT_tiny_rotate_270:
@ -1685,7 +1717,21 @@ tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
accent_mat.set_row(3, trans);
accent_geom->transform_vertices(accent_mat);
if (mirrored) {
// Once someone asks for this pointer, we hold its reference
// count and never free it.
static CPT(RenderState) disable_backface;
if (disable_backface == (const RenderState *)NULL) {
disable_backface = RenderState::make
(CullFaceAttrib::make(CullFaceAttrib::M_cull_none));
}
CPT(RenderState) state =
accent_glyph->get_state()->compose(disable_backface);
dest->add_geom(accent_geom, state);
} else {
dest->add_geom(accent_geom, accent_glyph->get_state());
}
geom_array[num_geoms++] = accent_geom;
return true;

View File

@ -84,8 +84,10 @@ PUBLISHED:
INLINE static void set_default_encoding(Encoding encoding);
INLINE static Encoding get_default_encoding();
/*
INLINE void set_expand_amp(bool expand_amp);
INLINE bool get_expand_amp() const;
*/
INLINE float get_line_height() const;
@ -180,15 +182,21 @@ PUBLISHED:
INLINE CoordinateSystem get_coordinate_system() const;
INLINE void set_text(const string &text);
INLINE void set_text(const string &text, Encoding encoding);
INLINE void clear_text();
INLINE bool has_text() const;
INLINE string get_text() const;
INLINE string get_text(Encoding encoding) const;
INLINE void append_text(const string &text);
INLINE void append_char(int character);
INLINE void append_unicode_char(int character);
INLINE int get_num_chars() const;
INLINE int get_char(int index) const;
INLINE int get_unicode_char(int index) const;
INLINE string get_encoded_char(int index) const;
INLINE string get_encoded_char(int index, Encoding encoding) const;
INLINE string get_text_as_ascii() const;
INLINE static string reencode_text(const string &text, Encoding from, Encoding to);
INLINE float calc_width(int character) const;
INLINE float calc_width(const string &line) const;
string wordwrap_to(const string &text, float wordwrap_width,
@ -225,9 +233,11 @@ public:
INLINE wstring wordwrap_to(const wstring &wtext, float wordwrap_width,
bool preserve_trailing_whitespace) const;
string encode_wchar(wchar_t ch) const;
string encode_wtext(const wstring &wtext) const;
wstring decode_text(const string &text) const;
static string encode_wchar(wchar_t ch, Encoding encoding);
INLINE string encode_wtext(const wstring &wtext) const;
static string encode_wtext(const wstring &wtext, Encoding encoding);
INLINE wstring decode_text(const string &text) const;
static wstring decode_text(const string &text, Encoding encoding);
// From parent class PandaNode
virtual int get_unsafe_to_apply_attribs() const;
@ -245,8 +255,8 @@ public:
virtual BoundingVolume *recompute_internal_bound();
private:
wstring decode_text_impl(StringDecoder &decoder) const;
int expand_amp_sequence(StringDecoder &decoder) const;
static wstring decode_text_impl(StringDecoder &decoder);
// int expand_amp_sequence(StringDecoder &decoder) const;
INLINE void invalidate_no_measure();
INLINE void invalidate_with_measure();
@ -344,7 +354,7 @@ private:
F_frame_corners = 0x00000100,
F_card_transp = 0x00000200,
F_has_card_border = 0x00000400,
F_expand_amp = 0x00000800,
// F_expand_amp = 0x00000800,
F_got_text = 0x00001000,
F_got_wtext = 0x00002000,
F_needs_rebuild = 0x00004000,