From 9ef4d0c9d79810a259326fcf9484b2e35a2867f9 Mon Sep 17 00:00:00 2001 From: JoeDow Date: Sat, 26 Jul 2025 19:50:13 +0800 Subject: [PATCH] layout: Correctly marking box damage when text-related style changed (#38059) This change aims to supplement the missing incremental box tree construction when text-related styles change. Since certain text style adjustments can alter visible text content and typography. Therefore, the parent nodes of such text are marked as needing to re-collect their box tree children to ensure the correct display of text. Signed-off-by: sharpshooter_pt --- components/script/layout_dom/element.rs | 25 +++++++++++++++ tests/wpt/meta/MANIFEST.json | 17 ++++++++++ .../css/css-text/white-space/pre-001.html | 31 +++++++++++++++++++ .../white-space/reference/pre-001-ref.html | 19 ++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 tests/wpt/tests/css/css-text/white-space/pre-001.html create mode 100644 tests/wpt/tests/css/css-text/white-space/reference/pre-001-ref.html diff --git a/components/script/layout_dom/element.rs b/components/script/layout_dom/element.rs index 0fd806ab388..3003c352920 100644 --- a/components/script/layout_dom/element.rs +++ b/components/script/layout_dom/element.rs @@ -658,8 +658,33 @@ impl<'dom> style::dom::TElement for ServoLayoutElement<'dom> { false }; + let text_shaping_needs_recollect = || { + if old.clone_direction() != new.clone_direction() || + old.clone_unicode_bidi() != new.clone_unicode_bidi() + { + return true; + } + + let old_text = old.get_inherited_text().clone(); + let new_text = new.get_inherited_text().clone(); + if old_text.white_space_collapse != new_text.white_space_collapse || + old_text.text_transform != new_text.text_transform || + old_text.word_break != new_text.word_break || + old_text.overflow_wrap != new_text.overflow_wrap || + old_text.letter_spacing != new_text.letter_spacing || + old_text.word_spacing != new_text.word_spacing || + old_text.text_rendering != new_text.text_rendering + { + return true; + } + + false + }; + if box_tree_needs_rebuild() { RestyleDamage::from_bits_retain(LayoutDamage::REBUILD_BOX.bits()) + } else if text_shaping_needs_recollect() { + RestyleDamage::from_bits_retain(LayoutDamage::RECOLLECT_BOX_TREE_CHILDREN.bits()) } else { // This element needs to be laid out again, but does not have any damage to // its box. In the future, we will distinguish between types of damage to the diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 80ac26a5d14..42e1f741a8c 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -271423,6 +271423,19 @@ {} ] ], + "pre-001.html": [ + "0e3e1e38c7293303d7cf07c0e64facfa76ba966d", + [ + null, + [ + [ + "/css/css-text/white-space/reference/pre-001-ref.html", + "==" + ] + ], + {} + ] + ], "pre-float-001.html": [ "8dd08d80992e6d6310a6697f84c2533d399c8e5e", [ @@ -453875,6 +453888,10 @@ "644dfc4b025e62babeddd3575af5ffee40c77e26", [] ], + "pre-001-ref.html": [ + "e950bbbc4960c650cd08b2532e6b0a3309ca5ffb", + [] + ], "pre-float-001-ref.html": [ "9753cb37b641f3f25d1045f3149875deffb1613c", [] diff --git a/tests/wpt/tests/css/css-text/white-space/pre-001.html b/tests/wpt/tests/css/css-text/white-space/pre-001.html new file mode 100644 index 00000000000..0e3e1e38c72 --- /dev/null +++ b/tests/wpt/tests/css/css-text/white-space/pre-001.html @@ -0,0 +1,31 @@ + +CSS-white-space test: restore collapsed whitespace + + + + + + +
+ aa bb target bb aa +
+ + + diff --git a/tests/wpt/tests/css/css-text/white-space/reference/pre-001-ref.html b/tests/wpt/tests/css/css-text/white-space/reference/pre-001-ref.html new file mode 100644 index 00000000000..e950bbbc496 --- /dev/null +++ b/tests/wpt/tests/css/css-text/white-space/reference/pre-001-ref.html @@ -0,0 +1,19 @@ + + + + +
+ aa bb target bb aa +
+