From 4e8bbd88059a7acb959a12c0afacbd4608fc44a4 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 1 Oct 2023 00:30:49 +0000 Subject: [PATCH] Bug 1731541 - When line-clamp is in effect, make text-wrap:balance consider only the lines up to the clamp limit. r=emilio This corresponds to how Chrome behaves, and passes the test they included in WPT. It's unclear to me whether this behavior actually follows from the current spec (see https://github.com/w3c/csswg-drafts/issues/9310), but it seems to be the desired result. (I've put it behind a (default-enabled) pref for now, so that it's possible to experiment with the two possible interpretations, but we can remove the pref once the spec question is clarified/confirmed.) This patch also disables balancing for fragmented/overflowing blocks, as that will not currently work well. We may want to address that as a followup issue (though it won't matter to the primary balance use-cases such as titles). Depends on D188139 Differential Revision: https://phabricator.services.mozilla.com/D188220 UltraBlame original commit: 8c9ba927121cd7f1cb5b31ffb86addc4c34b59a8 --- layout/generic/nsBlockFrame.cpp | 363 ++++++++++++++++-- modules/libpref/init/StaticPrefList.yaml | 27 ++ .../text-wrap-balance-line-clamp-001.html.ini | 18 - 3 files changed, 355 insertions(+), 53 deletions(-) delete mode 100644 testing/web-platform/meta/css/css-text/white-space/text-wrap-balance-line-clamp-001.html.ini diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index eb3bdc874dcf0..72390971bd2a4 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -7622,12 +7622,78 @@ GetPrevContinuation ( ) ; +struct +BalanceTarget +{ +nsIContent +* +mContent += +nullptr +; int32_t -balanceTarget +mOffset = - 1 ; +bool +operator += += +( +const +BalanceTarget +& +aOther +) +const +{ +return +mContent += += +aOther +. +mContent +& +& +mOffset += += +aOther +. +mOffset +; +} +bool +operator +! += +( +const +BalanceTarget +& +aOther +) +const +{ +return +! +( +* +this += += +aOther +) +; +} +} +; +BalanceTarget +balanceTarget +; auto countLinesUpTo = @@ -7692,6 +7758,131 @@ n ; } ; +auto +getClampPosition += +[ +& +] +( +uint32_t +aClampCount +) +- +> +BalanceTarget +{ +MOZ_ASSERT +( +aClampCount +< +mLines +. +size +( +) +) +; +auto +iter += +mLines +. +begin +( +) +; +for +( +uint32_t +i += +0 +; +i +< +aClampCount +; +i ++ ++ +) +{ ++ ++ +iter +; +} +nsIContent +* +content += +iter +- +> +mFirstChild +- +> +GetContent +( +) +; +int32_t +offset += +0 +; +if +( +content +& +& +iter +- +> +mFirstChild +- +> +IsTextFrame +( +) +) +{ +auto +* +textFrame += +static_cast +< +nsTextFrame +* +> +( +iter +- +> +mFirstChild +) +; +offset += +textFrame +- +> +GetContentOffset +( +) +; +} +return +BalanceTarget +{ +content +offset +} +; +} +; nscoord balanceStep = @@ -7774,6 +7965,8 @@ break ; } balanceTarget +. +mOffset = countLinesUpTo ( @@ -7788,6 +7981,8 @@ layout_css_text_wrap_balance_limit if ( balanceTarget +. +mOffset < 2 ) @@ -7804,6 +7999,8 @@ ComputedISize ) / balanceTarget +. +mOffset ; trialState . @@ -7817,6 +8014,66 @@ balanceStep = 2 ; +if +( +StaticPrefs +: +: +layout_css_text_wrap_balance_after_clamp_enabled +( +) +& +& +IsLineClampRoot +( +this +) +) +{ +uint32_t +lineClampCount += +aReflowInput +. +mStyleDisplay +- +> +mWebkitLineClamp +; +if +( +uint32_t +( +balanceTarget +. +mOffset +) +> +lineClampCount +) +{ +auto +t += +getClampPosition +( +lineClampCount +) +; +if +( +t +. +mContent +) +{ +balanceTarget += +t +; +} +} +} aReflowInput . mFloatManager @@ -7831,13 +8088,59 @@ floatManagerState continue ; } -if +auto +trialSucceeded += +[ +& +] ( -balanceStep +) +- > -0 +bool +{ +if +( +! +reflowStatus +. +IsFullyComplete +( +) ) { +return +false +; +} +if +( +balanceTarget +. +mContent +) +{ +auto +t += +getClampPosition +( +aReflowInput +. +mStyleDisplay +- +> +mWebkitLineClamp +) +; +return +t += += +balanceTarget +; +} int32_t numLines = @@ -7851,19 +8154,28 @@ layout_css_text_wrap_balance_limit ) ) ; -if -( -reflowStatus -. -IsFullyComplete -( -) -& -& +return numLines = = balanceTarget +. +mOffset +; +} +; +if +( +balanceStep +> +0 +) +{ +if +( +trialSucceeded +( +) ) { trialState @@ -7907,37 +8219,18 @@ continue if ( balanceTarget +. +mOffset > = 0 ) { -int32_t -numLines -= -countLinesUpTo -( -StaticPrefs -: -: -layout_css_text_wrap_balance_limit -( -) -) -; if ( -reflowStatus -. -IsFullyComplete +trialSucceeded ( ) -& -& -numLines -= -= -balanceTarget ) { break diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 89bba5172549e..1509191d8a3ce 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -54334,6 +54334,33 @@ value mirror : always +- +name +: +layout +. +css +. +text +- +wrap +- +balance +- +after +- +clamp +. +enabled +type +: +bool +value +: +true +mirror +: +always # Support for diff --git a/testing/web-platform/meta/css/css-text/white-space/text-wrap-balance-line-clamp-001.html.ini b/testing/web-platform/meta/css/css-text/white-space/text-wrap-balance-line-clamp-001.html.ini deleted file mode 100644 index 3a45e500ee867..0000000000000 --- a/testing/web-platform/meta/css/css-text/white-space/text-wrap-balance-line-clamp-001.html.ini +++ /dev/null @@ -1,18 +0,0 @@ -[ -text -- -wrap -- -balance -- -line -- -clamp -- -001 -. -html -] -expected -: -FAIL