You've already forked godot
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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user