Browse Source

[TextServer] Fix issues with character breaks, add more tests.

bruvzg 2 years ago
parent
commit
07d859de25

+ 3 - 4
modules/text_server_adv/text_server_adv.cpp

@@ -4864,8 +4864,7 @@ void TextServerAdvanced::_update_chars(ShapedTextDataAdvanced *p_sd) const {
 			while (i + 1 < spans.size() && language == spans[i + 1].language) {
 			while (i + 1 < spans.size() && language == spans[i + 1].language) {
 				i++;
 				i++;
 			}
 			}
-			int r_end = MIN(spans[i].end - p_sd->start, p_sd->text.size());
-
+			int r_end = MIN(spans[i].end - p_sd->start, p_sd->text.length());
 			UBreakIterator *bi = ubrk_open(UBRK_CHARACTER, (language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale().ascii().get_data() : language.ascii().get_data(), data + _convert_pos_inv(p_sd, r_start), _convert_pos_inv(p_sd, r_end - r_start), &err);
 			UBreakIterator *bi = ubrk_open(UBRK_CHARACTER, (language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale().ascii().get_data() : language.ascii().get_data(), data + _convert_pos_inv(p_sd, r_start), _convert_pos_inv(p_sd, r_end - r_start), &err);
 			if (U_SUCCESS(err)) {
 			if (U_SUCCESS(err)) {
 				while (ubrk_next(bi) != UBRK_DONE) {
 				while (ubrk_next(bi) != UBRK_DONE) {
@@ -4877,9 +4876,9 @@ void TextServerAdvanced::_update_chars(ShapedTextDataAdvanced *p_sd) const {
 				}
 				}
 				ubrk_close(bi);
 				ubrk_close(bi);
 			} else {
 			} else {
-				for (int j = r_start; j <= r_end; j++) {
+				for (int j = r_start; j < r_end; j++) {
 					if (prev != j) {
 					if (prev != j) {
-						p_sd->chars.push_back(j + p_sd->start);
+						p_sd->chars.push_back(j + 1 + p_sd->start);
 					}
 					}
 					prev = j;
 					prev = j;
 				}
 				}

+ 9 - 3
modules/text_server_fb/text_server_fb.cpp

@@ -4084,11 +4084,17 @@ PackedInt32Array TextServerFallback::_shaped_text_get_character_breaks(const RID
 	ERR_FAIL_COND_V(!sd, PackedInt32Array());
 	ERR_FAIL_COND_V(!sd, PackedInt32Array());
 
 
 	MutexLock lock(sd->mutex);
 	MutexLock lock(sd->mutex);
+	if (!sd->valid) {
+		const_cast<TextServerFallback *>(this)->_shaped_text_shape(p_shaped);
+	}
 
 
 	PackedInt32Array ret;
 	PackedInt32Array ret;
-	ret.resize(sd->end - sd->start);
-	for (int i = sd->start; i < sd->end; i++) {
-		ret.write[i] = i;
+	int size = sd->end - sd->start;
+	if (size > 0) {
+		ret.resize(size);
+		for (int i = 0; i < size; i++) {
+			ret.write[i] = i + 1 + sd->start;
+		}
 	}
 	}
 	return ret;
 	return ret;
 }
 }

+ 5 - 3
servers/text_server.cpp

@@ -1474,9 +1474,11 @@ int64_t TextServer::shaped_text_closest_character_pos(const RID &p_shaped, int64
 
 
 PackedInt32Array TextServer::string_get_character_breaks(const String &p_string, const String &p_language) const {
 PackedInt32Array TextServer::string_get_character_breaks(const String &p_string, const String &p_language) const {
 	PackedInt32Array ret;
 	PackedInt32Array ret;
-	ret.resize(p_string.size());
-	for (int i = 0; i <= p_string.size(); i++) {
-		ret.write[i] = i;
+	if (!p_string.is_empty()) {
+		ret.resize(p_string.size() - 1);
+		for (int i = 0; i < p_string.size() - 1; i++) {
+			ret.write[i] = i + 1;
+		}
 	}
 	}
 	return ret;
 	return ret;
 }
 }

+ 80 - 0
tests/servers/test_text_server.h

@@ -175,16 +175,96 @@ TEST_SUITE("[TextServer]") {
 
 
 				RID font1 = ts->create_font();
 				RID font1 = ts->create_font();
 				ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
 				ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
+				ts->font_set_allow_system_fallback(font1, false);
 				RID font2 = ts->create_font();
 				RID font2 = ts->create_font();
 				ts->font_set_data_ptr(font2, _font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size);
 				ts->font_set_data_ptr(font2, _font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size);
+				ts->font_set_allow_system_fallback(font2, false);
 				RID font3 = ts->create_font();
 				RID font3 = ts->create_font();
 				ts->font_set_data_ptr(font3, _font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size);
 				ts->font_set_data_ptr(font3, _font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size);
+				ts->font_set_allow_system_fallback(font3, false);
 
 
 				Array font;
 				Array font;
 				font.push_back(font1);
 				font.push_back(font1);
 				font.push_back(font2);
 				font.push_back(font2);
 				font.push_back(font3);
 				font.push_back(font3);
 
 
+				{
+					RID ctx = ts->create_shaped_text();
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
+					ts->shaped_text_add_string(ctx, U"Xtest", font, 10);
+					ts->shaped_text_add_string(ctx, U"xs", font, 10);
+					RID sctx = ts->shaped_text_substr(ctx, 1, 5);
+					CHECK_FALSE_MESSAGE(sctx == RID(), "Creating substring text buffer failed.");
+					PackedInt32Array sbrk = ts->shaped_text_get_character_breaks(sctx);
+					CHECK_FALSE_MESSAGE(sbrk.size() != 5, "Invalid substring char breaks number.");
+					if (sbrk.size() == 5) {
+						CHECK_FALSE_MESSAGE(sbrk[0] != 2, "Invalid substring char break position.");
+						CHECK_FALSE_MESSAGE(sbrk[1] != 3, "Invalid substring char break position.");
+						CHECK_FALSE_MESSAGE(sbrk[2] != 4, "Invalid substring char break position.");
+						CHECK_FALSE_MESSAGE(sbrk[3] != 5, "Invalid substring char break position.");
+						CHECK_FALSE_MESSAGE(sbrk[4] != 6, "Invalid substring char break position.");
+					}
+					PackedInt32Array fbrk = ts->shaped_text_get_character_breaks(ctx);
+					CHECK_FALSE_MESSAGE(fbrk.size() != 7, "Invalid char breaks number.");
+					if (fbrk.size() == 7) {
+						CHECK_FALSE_MESSAGE(fbrk[0] != 1, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[1] != 2, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[2] != 3, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[3] != 4, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[4] != 5, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[5] != 6, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[6] != 7, "Invalid char break position.");
+					}
+					PackedInt32Array rbrk = ts->string_get_character_breaks(U"Xtestxs");
+					CHECK_FALSE_MESSAGE(rbrk.size() != 7, "Invalid char breaks number.");
+					if (rbrk.size() == 7) {
+						CHECK_FALSE_MESSAGE(rbrk[0] != 1, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[1] != 2, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[2] != 3, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[3] != 4, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[4] != 5, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[5] != 6, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[6] != 7, "Invalid char break position.");
+					}
+
+					ts->free_rid(sctx);
+					ts->free_rid(ctx);
+				}
+
+				if (ts->has_feature(TextServer::FEATURE_BREAK_ITERATORS)) {
+					RID ctx = ts->create_shaped_text();
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
+					ts->shaped_text_add_string(ctx, U"X❤️‍🔥", font, 10);
+					ts->shaped_text_add_string(ctx, U"xs", font, 10);
+					RID sctx = ts->shaped_text_substr(ctx, 1, 5);
+					CHECK_FALSE_MESSAGE(sctx == RID(), "Creating substring text buffer failed.");
+					PackedInt32Array sbrk = ts->shaped_text_get_character_breaks(sctx);
+					CHECK_FALSE_MESSAGE(sbrk.size() != 2, "Invalid substring char breaks number.");
+					if (sbrk.size() == 2) {
+						CHECK_FALSE_MESSAGE(sbrk[0] != 5, "Invalid substring char break position.");
+						CHECK_FALSE_MESSAGE(sbrk[1] != 6, "Invalid substring char break position.");
+					}
+					PackedInt32Array fbrk = ts->shaped_text_get_character_breaks(ctx);
+					CHECK_FALSE_MESSAGE(fbrk.size() != 4, "Invalid char breaks number.");
+					if (fbrk.size() == 4) {
+						CHECK_FALSE_MESSAGE(fbrk[0] != 1, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[1] != 5, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[2] != 6, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(fbrk[3] != 7, "Invalid char break position.");
+					}
+					PackedInt32Array rbrk = ts->string_get_character_breaks(U"X❤️‍🔥xs");
+					CHECK_FALSE_MESSAGE(rbrk.size() != 4, "Invalid char breaks number.");
+					if (rbrk.size() == 4) {
+						CHECK_FALSE_MESSAGE(rbrk[0] != 1, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[1] != 5, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[2] != 6, "Invalid char break position.");
+						CHECK_FALSE_MESSAGE(rbrk[3] != 7, "Invalid char break position.");
+					}
+
+					ts->free_rid(sctx);
+					ts->free_rid(ctx);
+				}
+
 				{
 				{
 					String test = U"Test test long text long text\n";
 					String test = U"Test test long text long text\n";
 					RID ctx = ts->create_shaped_text();
 					RID ctx = ts->create_shaped_text();