Browse Source

Fix RichTextLabel auto-wrapping on CJK

Haoyu Qiu 4 years ago
parent
commit
3a591aaeeb
2 changed files with 30 additions and 3 deletions
  1. 9 3
      scene/gui/label.cpp
  2. 21 0
      scene/gui/rich_text_label.cpp

+ 9 - 3
scene/gui/label.cpp

@@ -393,11 +393,17 @@ void Label::regenerate_word_cache() {
 			current = String::char_uppercase(current);
 			current = String::char_uppercase(current);
 		}
 		}
 
 
-		// ranges taken from http://www.unicodemap.org/
+		// ranges taken from https://en.wikipedia.org/wiki/Plane_(Unicode)
 		// if your language is not well supported, consider helping improve
 		// if your language is not well supported, consider helping improve
 		// the unicode support in Godot.
 		// the unicode support in Godot.
-		bool separatable = (current >= 0x2E08 && current <= 0xFAFF) || (current >= 0xFE30 && current <= 0xFE4F);
-		//current>=33 && (current < 65||current >90) && (current<97||current>122) && (current<48||current>57);
+		bool separatable = (current >= 0x2E08 && current <= 0x9FFF) || // CJK scripts and symbols.
+						   (current >= 0xAC00 && current <= 0xD7FF) || // Hangul Syllables and Hangul Jamo Extended-B.
+						   (current >= 0xF900 && current <= 0xFAFF) || // CJK Compatibility Ideographs.
+						   (current >= 0xFE30 && current <= 0xFE4F) || // CJK Compatibility Forms.
+						   (current >= 0xFF65 && current <= 0xFF9F) || // Halfwidth forms of katakana
+						   (current >= 0xFFA0 && current <= 0xFFDC) || // Halfwidth forms of compatibility jamo characters for Hangul
+						   (current >= 0x20000 && current <= 0x2FA1F) || // CJK Unified Ideographs Extension B ~ F and CJK Compatibility Ideographs Supplement.
+						   (current >= 0x30000 && current <= 0x3134F); // CJK Unified Ideographs Extension G.
 		bool insert_newline = false;
 		bool insert_newline = false;
 		real_t char_width = 0;
 		real_t char_width = 0;
 
 

+ 21 - 0
scene/gui/rich_text_label.cpp

@@ -386,12 +386,14 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 					l.char_count += text->text.length();
 					l.char_count += text->text.length();
 				}
 				}
 
 
+				bool just_breaked_in_middle = false;
 				rchar = 0;
 				rchar = 0;
 				FontDrawer drawer(font, Color(1, 1, 1));
 				FontDrawer drawer(font, Color(1, 1, 1));
 				while (*c) {
 				while (*c) {
 					int end = 0;
 					int end = 0;
 					int w = 0;
 					int w = 0;
 					int fw = 0;
 					int fw = 0;
+					bool was_separatable = false;
 
 
 					lh = 0;
 					lh = 0;
 
 
@@ -410,6 +412,25 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 							break; //don't allow lines longer than assigned width
 							break; //don't allow lines longer than assigned width
 						}
 						}
 
 
+						// For info about the unicode range, see Label::regenerate_word_cache.
+						const CharType current = c[end];
+						const bool separatable = (current >= 0x2E08 && current <= 0x9FFF) || // CJK scripts and symbols.
+												 (current >= 0xAC00 && current <= 0xD7FF) || // Hangul Syllables and Hangul Jamo Extended-B.
+												 (current >= 0xF900 && current <= 0xFAFF) || // CJK Compatibility Ideographs.
+												 (current >= 0xFE30 && current <= 0xFE4F) || // CJK Compatibility Forms.
+												 (current >= 0xFF65 && current <= 0xFF9F) || // Halfwidth forms of katakana
+												 (current >= 0xFFA0 && current <= 0xFFDC) || // Halfwidth forms of compatibility jamo characters for Hangul
+												 (current >= 0x20000 && current <= 0x2FA1F) || // CJK Unified Ideographs Extension B ~ F and CJK Compatibility Ideographs Supplement.
+												 (current >= 0x30000 && current <= 0x3134F); // CJK Unified Ideographs Extension G.
+						const bool long_separatable = separatable && (wofs - backtrack + w + cw > p_width);
+						const bool separation_changed = end > 0 && was_separatable != separatable;
+						if (!just_breaked_in_middle && (long_separatable || separation_changed)) {
+							just_breaked_in_middle = true;
+							break;
+						}
+						was_separatable = separatable;
+						just_breaked_in_middle = false;
+
 						w += cw;
 						w += cw;
 						fw += cw;
 						fw += cw;