1
0
mirror of https://github.com/godotengine/godot.git synced 2026-01-06 19:41:11 +00:00

Improve line BiDi handling, prevent crash on recursive log updates.

(cherry picked from commit 282e4231c2)
This commit is contained in:
bruvzg
2023-04-12 11:39:05 +03:00
committed by Yuri Sizov
parent 3a1af9393f
commit 9c1ea28092
5 changed files with 54 additions and 10 deletions

View File

@@ -4105,6 +4105,7 @@ RID TextServerAdvanced::_shaped_text_substr(const RID &p_shaped, int64_t p_start
new_sd->direction = sd->direction;
new_sd->custom_punct = sd->custom_punct;
new_sd->para_direction = sd->para_direction;
new_sd->base_para_direction = sd->base_para_direction;
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
new_sd->extra_spacing[i] = sd->extra_spacing[i];
}
@@ -4155,9 +4156,33 @@ bool TextServerAdvanced::_shape_substr(ShapedTextDataAdvanced *p_new_sd, const S
if (U_SUCCESS(err)) {
ubidi_setLine(p_sd->bidi_iter[ov], start, end, bidi_iter, &err);
if (U_FAILURE(err)) {
ubidi_close(bidi_iter);
bidi_iter = nullptr;
ERR_PRINT(vformat("BiDi reordering for the line failed: %s", u_errorName(err)));
// Line BiDi failed (string contains incompatible control characters), try full paragraph BiDi instead.
err = U_ZERO_ERROR;
const UChar *data = p_sd->utf16.get_data();
switch (static_cast<TextServer::Direction>(p_sd->bidi_override[ov].z)) {
case DIRECTION_LTR: {
ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_LTR, nullptr, &err);
} break;
case DIRECTION_RTL: {
ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_RTL, nullptr, &err);
} break;
case DIRECTION_INHERITED: {
ubidi_setPara(bidi_iter, data + start, end - start, p_sd->base_para_direction, nullptr, &err);
} break;
case DIRECTION_AUTO: {
UBiDiDirection direction = ubidi_getBaseDirection(data + start, end - start);
if (direction != UBIDI_NEUTRAL) {
ubidi_setPara(bidi_iter, data + start, end - start, direction, nullptr, &err);
} else {
ubidi_setPara(bidi_iter, data + start, end - start, p_sd->base_para_direction, nullptr, &err);
}
} break;
}
if (U_FAILURE(err)) {
ubidi_close(bidi_iter);
bidi_iter = nullptr;
ERR_PRINT(vformat("BiDi reordering for the line failed: %s", u_errorName(err)));
}
}
} else {
bidi_iter = nullptr;
@@ -5586,25 +5611,25 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
sd->script_iter = memnew(ScriptIterator(sd->text, 0, sd->text.length()));
}
int base_para_direction = UBIDI_DEFAULT_LTR;
sd->base_para_direction = UBIDI_DEFAULT_LTR;
switch (sd->direction) {
case DIRECTION_LTR: {
sd->para_direction = DIRECTION_LTR;
base_para_direction = UBIDI_LTR;
sd->base_para_direction = UBIDI_LTR;
} break;
case DIRECTION_RTL: {
sd->para_direction = DIRECTION_RTL;
base_para_direction = UBIDI_RTL;
sd->base_para_direction = UBIDI_RTL;
} break;
case DIRECTION_INHERITED:
case DIRECTION_AUTO: {
UBiDiDirection direction = ubidi_getBaseDirection(data, sd->utf16.length());
if (direction != UBIDI_NEUTRAL) {
sd->para_direction = (direction == UBIDI_RTL) ? DIRECTION_RTL : DIRECTION_LTR;
base_para_direction = direction;
sd->base_para_direction = direction;
} else {
sd->para_direction = DIRECTION_LTR;
base_para_direction = UBIDI_DEFAULT_LTR;
sd->base_para_direction = UBIDI_DEFAULT_LTR;
}
} break;
}
@@ -5633,14 +5658,14 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_RTL, nullptr, &err);
} break;
case DIRECTION_INHERITED: {
ubidi_setPara(bidi_iter, data + start, end - start, base_para_direction, nullptr, &err);
ubidi_setPara(bidi_iter, data + start, end - start, sd->base_para_direction, nullptr, &err);
} break;
case DIRECTION_AUTO: {
UBiDiDirection direction = ubidi_getBaseDirection(data + start, end - start);
if (direction != UBIDI_NEUTRAL) {
ubidi_setPara(bidi_iter, data + start, end - start, direction, nullptr, &err);
} else {
ubidi_setPara(bidi_iter, data + start, end - start, base_para_direction, nullptr, &err);
ubidi_setPara(bidi_iter, data + start, end - start, sd->base_para_direction, nullptr, &err);
}
} break;
}