From 56a9f1feaec42c38b76da676f4abde76dc4b2b3a Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 4 Mar 2004 19:14:58 +0000 Subject: [PATCH] add text-soft-break-key and text-never-break-before --- panda/src/text/config_text.cxx | 24 +++++++++++++++++++++--- panda/src/text/config_text.h | 3 +++ panda/src/text/textFont.cxx | 26 +++++++++++++++++++++----- panda/src/text/textNode.cxx | 12 ++++++++++-- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/panda/src/text/config_text.cxx b/panda/src/text/config_text.cxx index 681f48729c..c861fe35e7 100644 --- a/panda/src/text/config_text.cxx +++ b/panda/src/text/config_text.cxx @@ -52,14 +52,29 @@ const float text_tab_width = config_text.GetFloat("text-tab-width", 5.0f); // identified as the soft-hyphen character. const int text_soft_hyphen_key = config_text.GetInt("text-soft-hyphen-key", 3); +// This is similar to the soft-hyphen key, above, except that when it +// is used as a break point, no character is introduced in its place. +const int text_soft_break_key = config_text.GetInt("text-soft-break-key", 4); + // This is the string that is output, encoded in the default encoding, -// to represent the soft-hyphen character. +// to represent the hyphen character that is introduced when the line +// is broken at a soft-hyphen key. wstring *text_soft_hyphen_output; // If the rightmost whitespace character falls before this fraction of // the line, hyphenate a word to the right of that if possible. const float text_hyphen_ratio = config_text.GetFloat("text-hyphen-ratio", 0.7); +// This string represents a list of individual characters that should +// never appear at the beginning of a line following a forced break. +// Typically these will be punctuation characters. +wstring *text_never_break_before; + +// Unless we have more than this number of text_never_break_before +// characters in a row, in which case forget it and break wherever we +// can. +const int text_max_never_break = config_text.GetInt("text-max-never-break", 3); + Texture::FilterType text_minfilter = Texture::FT_invalid; Texture::FilterType text_magfilter = Texture::FT_invalid; @@ -119,7 +134,10 @@ init_libtext() { // Make sure libexpress is initialized before we ask something of // TextEncoder. init_libexpress(); - string encoded = config_text.GetString("text-soft-hyphen-output", "-"); TextEncoder encoder; - text_soft_hyphen_output = new wstring(encoder.decode_text(encoded)); + string st1 = config_text.GetString("text-soft-hyphen-output", "-"); + text_soft_hyphen_output = new wstring(encoder.decode_text(st1)); + + string st2 = config_text.GetString("text-never-break-before", ",.-:?!;"); + text_never_break_before = new wstring(encoder.decode_text(st2)); } diff --git a/panda/src/text/config_text.h b/panda/src/text/config_text.h index 9def50533a..064027d8a4 100644 --- a/panda/src/text/config_text.h +++ b/panda/src/text/config_text.h @@ -39,8 +39,11 @@ extern const float text_small_caps_scale; extern const string text_default_font; extern const float text_tab_width; extern const int text_soft_hyphen_key; +extern const int text_soft_break_key; extern wstring *text_soft_hyphen_output; extern const float text_hyphen_ratio; +extern wstring *text_never_break_before; +extern const int text_max_never_break; extern Texture::FilterType text_minfilter; extern Texture::FilterType text_magfilter; diff --git a/panda/src/text/textFont.cxx b/panda/src/text/textFont.cxx index 7d9941330c..88b77a6631 100644 --- a/panda/src/text/textFont.cxx +++ b/panda/src/text/textFont.cxx @@ -30,7 +30,9 @@ TypeHandle TextFont::_type_handle; //////////////////////////////////////////////////////////////////// static INLINE bool isbreakpoint(unsigned int ch) { - return (ch == ' ' || ch == '\t' || ch == (unsigned int)text_soft_hyphen_key); + return (ch == ' ' || ch == '\t' || + ch == (unsigned int)text_soft_hyphen_key || + ch == (unsigned int)text_soft_break_key); } //////////////////////////////////////////////////////////////////// @@ -219,7 +221,7 @@ wordwrap_to(const wstring &text, float wordwrap_width, float hyphen_width = calc_width(*text_soft_hyphen_output); float width = initial_width; while (q < text.length() && text[q] != '\n') { - if (isspacew(text[q])) { + if (isspacew(text[q]) || text[q] == text_soft_break_key) { if (!last_was_space) { any_spaces = true; // We only care about logging whether there is a soft-hyphen @@ -235,7 +237,7 @@ wordwrap_to(const wstring &text, float wordwrap_width, } // A soft hyphen character is not printed, but marks a point - // that we might hyphenate a word if we need to. + // at which we might hyphenate a word if we need to. if (text[q] == text_soft_hyphen_key) { // We only consider this as a possible hyphenation point if // (a) it is not the very first character, and (b) there is @@ -246,7 +248,7 @@ wordwrap_to(const wstring &text, float wordwrap_width, last_hyphen = q; } - } else { + } else if (text[q] != text_soft_break_key) { // Some normal, printable character. width += calc_width(text[q]); } @@ -279,6 +281,19 @@ wordwrap_to(const wstring &text, float wordwrap_width, } else if (any_spaces) { // Otherwise, break at a space if we can. q = last_space; + + } else { + // Otherwise, this is a forced break. Accept the longest line + // we can that does not leave the next line beginning with one + // of our forbidden characters. + size_t i = 0; + while (i < text_max_never_break && q - i > p && + text_never_break_before->find(text[q - i]) != wstring::npos) { + i++; + } + if (i < text_max_never_break) { + q -= i; + } } } @@ -314,7 +329,8 @@ wordwrap_to(const wstring &text, float wordwrap_width, } for (size_t pi = p; pi < q; pi++) { - if (text[pi] != text_soft_hyphen_key) { + if (text[pi] != text_soft_hyphen_key && + text[pi] != text_soft_break_key) { output_text += text[pi]; } } diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 273d05f1c9..601dd18ffb 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -142,10 +142,18 @@ TextNode:: string TextNode:: wordwrap_to(const string &text, float wordwrap_width, bool preserve_trailing_whitespace) const { - nassertr(_font != (TextFont *)NULL, text); + TextFont *font = get_font(); + if (font == (TextFont *)NULL) { + font = get_default_font(); + } + + if (font == (TextFont *)NULL) { + return text; + } + wstring decoded = decode_text(text); wstring wrapped = - _font->wordwrap_to(decoded, wordwrap_width, preserve_trailing_whitespace); + font->wordwrap_to(decoded, wordwrap_width, preserve_trailing_whitespace); return encode_wtext(wrapped); }