From 8fa484f331932526e9e4891f084186d4e889466b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Thu, 11 Dec 2025 21:50:22 +0200 Subject: [PATCH] [TextServer] Fix `duplicated` losing span info, and RID leak. --- modules/text_server_adv/text_server_adv.cpp | 10 ++++++++-- modules/text_server_fb/text_server_fb.cpp | 9 ++++++++- scene/resources/text_line.cpp | 1 + scene/resources/text_paragraph.cpp | 2 ++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 41cc7a71720..ef9f05a483c 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -4495,9 +4495,10 @@ RID TextServerAdvanced::_shaped_text_duplicate(const RID &p_shaped) { MutexLock lock(sd->mutex); ShapedTextDataAdvanced *new_sd = memnew(ShapedTextDataAdvanced); - new_sd->parent = p_shaped; new_sd->start = sd->start; new_sd->end = sd->end; + new_sd->first_span = sd->first_span; + new_sd->last_span = sd->last_span; new_sd->text = sd->text; new_sd->hb_buffer = hb_buffer_create(); new_sd->utf16 = new_sd->text.utf16(); @@ -4517,7 +4518,12 @@ RID TextServerAdvanced::_shaped_text_duplicate(const RID &p_shaped) { for (int i = 0; i < TextServer::SPACING_MAX; i++) { new_sd->extra_spacing[i] = sd->extra_spacing[i]; } - full_copy(new_sd); + for (const KeyValue &E : sd->objects) { + new_sd->objects[E.key] = E.value; + } + for (int i = 0; i < sd->spans.size(); i++) { + new_sd->spans.push_back(sd->spans[i]); + } new_sd->valid.clear(); return shaped_owner.make_rid(new_sd); diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 76d8530813b..7edd1ed8487 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -3336,6 +3336,8 @@ RID TextServerFallback::_shaped_text_duplicate(const RID &p_shaped) { new_sd->parent = p_shaped; new_sd->start = sd->start; new_sd->end = sd->end; + new_sd->first_span = sd->first_span; + new_sd->last_span = sd->last_span; new_sd->text = sd->text; new_sd->orientation = sd->orientation; new_sd->direction = sd->direction; @@ -3351,7 +3353,12 @@ RID TextServerFallback::_shaped_text_duplicate(const RID &p_shaped) { for (int i = 0; i < TextServer::SPACING_MAX; i++) { new_sd->extra_spacing[i] = sd->extra_spacing[i]; } - full_copy(new_sd); + for (const KeyValue &E : sd->objects) { + new_sd->objects[E.key] = E.value; + } + for (int i = 0; i < sd->spans.size(); i++) { + new_sd->spans.push_back(sd->spans[i]); + } new_sd->valid.clear(); return shaped_owner.make_rid(new_sd); diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp index a74359e25fd..459180dd572 100644 --- a/scene/resources/text_line.cpp +++ b/scene/resources/text_line.cpp @@ -155,6 +155,7 @@ Ref TextLine::duplicate() const { Ref copy; copy.instantiate(); if (rid.is_valid()) { + TS->free_rid(copy->rid); copy->rid = TS->shaped_text_duplicate(rid); } copy->dirty = true; diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index 35d8af36cb3..2f7097002b1 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -328,11 +328,13 @@ Ref TextParagraph::duplicate() const { Ref copy; copy.instantiate(); if (dropcap_rid.is_valid()) { + TS->free_rid(copy->dropcap_rid); copy->dropcap_rid = TS->shaped_text_duplicate(dropcap_rid); } copy->dropcap_lines = dropcap_lines; copy->dropcap_margins = dropcap_margins; if (rid.is_valid()) { + TS->free_rid(copy->rid); copy->rid = TS->shaped_text_duplicate(rid); } copy->lines_dirty = true;