Browse Source

add text-soft-break-key and text-never-break-before

David Rose 22 years ago
parent
commit
56a9f1feae

+ 21 - 3
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.
 // identified as the soft-hyphen character.
 const int text_soft_hyphen_key = config_text.GetInt("text-soft-hyphen-key", 3);
 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,
 // 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;
 wstring *text_soft_hyphen_output;
 
 
 // If the rightmost whitespace character falls before this fraction of
 // If the rightmost whitespace character falls before this fraction of
 // the line, hyphenate a word to the right of that if possible.
 // 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);
 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_minfilter = Texture::FT_invalid;
 Texture::FilterType text_magfilter = 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
   // Make sure libexpress is initialized before we ask something of
   // TextEncoder.
   // TextEncoder.
   init_libexpress();
   init_libexpress();
-  string encoded = config_text.GetString("text-soft-hyphen-output", "-");
   TextEncoder encoder;
   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));
 }
 }

+ 3 - 0
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 string text_default_font;
 extern const float text_tab_width;
 extern const float text_tab_width;
 extern const int text_soft_hyphen_key;
 extern const int text_soft_hyphen_key;
+extern const int text_soft_break_key;
 extern wstring *text_soft_hyphen_output;
 extern wstring *text_soft_hyphen_output;
 extern const float text_hyphen_ratio;
 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_minfilter;
 extern Texture::FilterType text_magfilter;
 extern Texture::FilterType text_magfilter;

+ 21 - 5
panda/src/text/textFont.cxx

@@ -30,7 +30,9 @@ TypeHandle TextFont::_type_handle;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 static INLINE bool
 static INLINE bool
 isbreakpoint(unsigned int ch) {
 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 hyphen_width = calc_width(*text_soft_hyphen_output);
     float width = initial_width;
     float width = initial_width;
     while (q < text.length() && text[q] != '\n') {
     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) {
         if (!last_was_space) {
           any_spaces = true;
           any_spaces = true;
           // We only care about logging whether there is a soft-hyphen
           // 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
       // 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) {
       if (text[q] == text_soft_hyphen_key) {
         // We only consider this as a possible hyphenation point if
         // We only consider this as a possible hyphenation point if
         // (a) it is not the very first character, and (b) there is
         // (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;
           last_hyphen = q;
         }
         }
 
 
-      } else {
+      } else if (text[q] != text_soft_break_key) {
         // Some normal, printable character.
         // Some normal, printable character.
         width += calc_width(text[q]);
         width += calc_width(text[q]);
       }
       }
@@ -279,6 +281,19 @@ wordwrap_to(const wstring &text, float wordwrap_width,
       } else if (any_spaces) {
       } else if (any_spaces) {
         // Otherwise, break at a space if we can.
         // Otherwise, break at a space if we can.
         q = last_space;
         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++) {
     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];
         output_text += text[pi];
       }
       }
     }
     }

+ 10 - 2
panda/src/text/textNode.cxx

@@ -142,10 +142,18 @@ TextNode::
 string TextNode::
 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);
+  TextFont *font = get_font();
+  if (font == (TextFont *)NULL) {
+    font = get_default_font();
+  }
+
+  if (font == (TextFont *)NULL) {
+    return text;
+  }
+
   wstring decoded = decode_text(text);
   wstring decoded = decode_text(text);
   wstring wrapped = 
   wstring wrapped = 
-    _font->wordwrap_to(decoded, wordwrap_width, preserve_trailing_whitespace);
+    font->wordwrap_to(decoded, wordwrap_width, preserve_trailing_whitespace);
   return encode_wtext(wrapped);
   return encode_wtext(wrapped);
 }
 }