Bug 1523595 Part 3 - Apply ColumnSetWrapper's block size constraint to the available size when creating BlockReflowInput for ColumnSet. r=dbaron

We used to apply the column container's block size constraint on top of
the available block size in nsColumnSetFrame::ChooseColumnStrategy().
After column-span is enabled, ColumnSet is no longer the outermost
column container frame. We need to apply ColumnSetWrapper's block size
constraint to the available size when creating the ReflowInput for
ColumnSet so that ColumnSet can use it to compute the max column block
size in ChooseColumnStrategy().

This is calculated in nsBlockFrame::ReflowBlockFrame() instead of
nsColumnSetFrame::ChooseColumnStrategy() because we need
BlockReflowInput::mBCoord to determine the remaining block size.

multicol-breaking-004.html is copied and modified from
multicol-breaking-001.html with border-bottom added to test
"box-decoration-break: clone".

Differential Revision: https://phabricator.services.mozilla.com/D31676

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ting-Yu Lin 2019-06-19 17:05:22 +00:00
Родитель 4547c3eb7d
Коммит 6c93720bad
11 изменённых файлов: 379 добавлений и 9 удалений

Просмотреть файл

@ -3604,6 +3604,7 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowInput& aState,
// Construct the reflow input for the block. // Construct the reflow input for the block.
Maybe<ReflowInput> blockReflowInput; Maybe<ReflowInput> blockReflowInput;
Maybe<LogicalSize> cbSize; Maybe<LogicalSize> cbSize;
LogicalSize availSize = availSpace.Size(wm);
if (Style()->GetPseudoType() == PseudoStyleType::columnContent) { if (Style()->GetPseudoType() == PseudoStyleType::columnContent) {
// Calculate the multicol containing block's block size so that the // Calculate the multicol containing block's block size so that the
// children with percentage block size get correct percentage basis. // children with percentage block size get correct percentage basis.
@ -3628,11 +3629,39 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowInput& aState,
frame->IsColumnSetWrapperFrame()) { frame->IsColumnSetWrapperFrame()) {
frame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); frame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
} }
} else if (IsColumnSetWrapperFrame()) {
// If we are reflowing our ColumnSet children, we want to apply our block
// size constraint to the available block size when constructing reflow
// input for ColumnSet so that ColumnSet can use it to compute its max
// column block size.
if (frame->IsColumnSetFrame()) {
if (availSize.BSize(wm) != NS_UNCONSTRAINEDSIZE) {
// If the available size is constrained, we need to subtract
// ColumnSetWrapper's block-end border and padding.
availSize.BSize(wm) -= aState.BorderPadding().BEnd(wm);
}
nscoord contentBSize = aState.mReflowInput.ComputedBSize();
if (aState.mReflowInput.ComputedMaxBSize() != NS_UNCONSTRAINEDSIZE) {
contentBSize =
std::min(contentBSize, aState.mReflowInput.ComputedMaxBSize());
}
if (contentBSize != NS_UNCONSTRAINEDSIZE) {
// ColumnSet is not the outermost frame in the column container, so it
// cannot have any margin. We don't need to consider any margin that
// can be generated by "box-decoration-break: clone" as we do in
// BlockReflowInput::ComputeBlockAvailSpace().
const nscoord availContentBSize = std::max(
0, contentBSize - (aState.mBCoord - aState.ContentBStart()));
availSize.BSize(wm) =
std::min(availSize.BSize(wm), availContentBSize);
}
}
} }
blockReflowInput.emplace( blockReflowInput.emplace(aState.mPresContext, aState.mReflowInput, frame,
aState.mPresContext, aState.mReflowInput, frame, availSize.ConvertTo(frame->GetWritingMode(), wm),
availSpace.Size(wm).ConvertTo(frame->GetWritingMode(), wm), cbSize); cbSize);
nsFloatManager::SavedState floatManagerState; nsFloatManager::SavedState floatManagerState;
nsReflowStatus frameReflowStatus; nsReflowStatus frameReflowStatus;

Просмотреть файл

@ -311,11 +311,6 @@ nsColumnSetFrame::ReflowConfig nsColumnSetFrame::ChooseColumnStrategy(
colBSize = aReflowInput.ComputedBSize(); colBSize = aReflowInput.ComputedBSize();
} else if (aReflowInput.ComputedMaxBSize() != NS_UNCONSTRAINEDSIZE) { } else if (aReflowInput.ComputedMaxBSize() != NS_UNCONSTRAINEDSIZE) {
colBSize = std::min(colBSize, aReflowInput.ComputedMaxBSize()); colBSize = std::min(colBSize, aReflowInput.ComputedMaxBSize());
} else if (StaticPrefs::layout_css_column_span_enabled() &&
aReflowInput.mCBReflowInput->ComputedMaxBSize() !=
NS_UNCONSTRAINEDSIZE) {
colBSize =
std::min(colBSize, aReflowInput.mCBReflowInput->ComputedMaxBSize());
} }
nscoord colGap = nscoord colGap =
@ -1064,6 +1059,8 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput,
} }
if (aConfig.mKnownInfeasibleBSize >= availableContentBSize) { if (aConfig.mKnownInfeasibleBSize >= availableContentBSize) {
// There's no feasible block-size to fit our contents. We may need to
// reflow one more time after this loop.
break; break;
} }
@ -1124,7 +1121,29 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput,
if (aConfig.mKnownInfeasibleBSize >= availableContentBSize) { if (aConfig.mKnownInfeasibleBSize >= availableContentBSize) {
aConfig.mColMaxBSize = availableContentBSize; aConfig.mColMaxBSize = availableContentBSize;
if (mLastBalanceBSize == availableContentBSize) { if (mLastBalanceBSize == availableContentBSize) {
skip = true; if (StaticPrefs::layout_css_column_span_enabled() &&
aUnboundedLastColumn &&
!aReflowInput.mCBReflowInput->mFrame->HasAnyStateBits(
NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
// If we are end up here, we have a constrained available content
// block size and cannot fit all the content during the very first
// balancing iteration. We may need to give up balancing and reflow
// again.
//
// Note that we do this only for the top-level column container
// because we don't want a nested column container to create overflow
// columns immediately if its content doesn't fit, and change its
// completeness from incomplete to complete. That is because 1) the
// top-level one might do column balancing, and it can enlarge the
// available block-size so that the nested one could fit its content
// in next balancing iteration; or 2) the top-level container is
// filling columns sequentially, and may have more inline-size to
// create more column boxes for the nested column containers'
// next-in-flow frames.
aConfig = ChooseColumnStrategy(aReflowInput, true);
} else {
skip = true;
}
} }
} else { } else {
aConfig.mColMaxBSize = aConfig.mKnownFeasibleBSize; aConfig.mColMaxBSize = aConfig.mKnownFeasibleBSize;

Просмотреть файл

@ -0,0 +1,2 @@
[multicol-breaking-004.html]
prefs: [layout.css.column-span.enabled:true]

Просмотреть файл

@ -0,0 +1,2 @@
[multicol-span-all-children-height-002.html]
prefs: [layout.css.column-span.enabled:true]

Просмотреть файл

@ -0,0 +1,2 @@
[multicol-span-all-children-height-003.html]
prefs: [layout.css.column-span.enabled:true]

Просмотреть файл

@ -0,0 +1,94 @@
<!DOCTYPE HTML>
<title>CSS Test Reference: breaking of a multicolumn</title>
<meta charset="utf-8">
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://mozilla.org/">
<style>
.outer {
height: 125px;
width: 800px;
background: rgba(0, 0, 255, 0.3);
position: relative;
}
.blueborders {
position: absolute;
top: 0;
left: 194px; /* 188px first column + (16px gap - 4px rule) / 2 */
width: 200px; /* 188px second column + (16px gap - 4px rule) */
height: 125px;
border-right: blue solid 4px;
border-left: blue solid 4px;
}
.innerbg {
height: 125px;
width: 188px;
background: rgba(255, 0, 255, 0.3);
position: absolute;
top: 0;
}
.inner {
height: 100px;
width: 86px;
font: 16px/1.25 sans-serif;
position: absolute;
top: 0;
}
.border-bottom {
height: 25px;
width: 188px;
background: green;
position: absolute;
top: 100px;
}
.lefthalf {
border-right: 2px solid fuchsia;
padding-right: 7px;
}
.righthalf {
padding-left: 7px;
}
</style>
<div class="outer">
<div class="blueborders"></div>
<div class="innerbg" style="left: 0"></div>
<div class="inner lefthalf" style="left: 0">
AAAAA<br>
BBBBB<br>
CCCCC<br>
DDDDD<br>
EEEEE
</div>
<div class="inner righthalf" style="left: 95px">
FFFFF<br>
GGGGG<br>
HHHHH<br>
IIIII<br>
JJJJJ
</div>
<div class="border-bottom" style="left: 0"></div>
<div class="innerbg" style="left: 204px"></div>
<div class="inner lefthalf" style="left: 204px; height: 80px">
KKKKK<br>
LLLLL<br>
MMMMM<br>
NNNNN
</div>
<div class="border-bottom" style="left: 204px;"></div>
<div class="inner righthalf" style="left: 299px">
OOOOO<br>
PPPPP<br>
QQQQQ<br>
</div>
<div class="innerbg" style="left: 408px"></div>
<div class="border-bottom" style="left: 408px"></div>
</div>

Просмотреть файл

@ -0,0 +1,56 @@
<!DOCTYPE HTML>
<title>CSS Test: breaking of a multicolumn</title>
<meta charset="utf-8">
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-multicol/#column-gaps-and-rules">
<link rel="help" href="https://drafts.csswg.org/css-multicol/#cf">
<link rel="help" href="https://drafts.csswg.org/css-break/#break-decoration">
<link rel="match" href="multicol-breaking-004-ref.html">
<style>
.outer {
height: 125px;
column-fill: auto;
width: 800px;
column-count: 4;
column-rule: 4px solid blue;
column-gap: 16px;
background: rgba(0, 0, 255, 0.3);
}
.inner {
column-count: 2;
column-rule: 2px solid fuchsia;
column-gap: 16px;
background: rgba(255, 0, 255, 0.3);
font: 16px/1.25 sans-serif;
border: solid green;
border-width: 0 0 25px 0;
box-decoration-break: clone;
}
</style>
<div class="outer">
<div class="inner" style="height: 300px">
AAAAA<br>
BBBBB<br>
CCCCC<br>
DDDDD<br>
EEEEE<br>
FFFFF<br>
GGGGG<br>
HHHHH<br>
IIIII<br>
JJJJJ<br>
KKKKK<br>
LLLLL<br>
MMMMM<br>
NNNNN<br>
OOOOO<br>
PPPPP<br>
QQQQQ
</div>
</div>

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>CSS Multi-column Layout Test Reference: Test a multi-column container with percentage height children</title>
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<style>
article {
width: 400px;
height: 200px;
background-color: lightgreen;
border: 5px solid purple;
}
div.columns {
column-count: 2;
}
div.block1 {
background-color: yellow;
height: 200px;
}
div.spanner {
height: 50px;
background-color: lightblue;
}
div.block2 {
background-color: yellow;
height: 200px;
}
</style>
<article>
<div class="columns" style="height: 100px;">
<div class="block1">block1</div>
</div>
<div class="spanner">spanner</div>
<div class="columns" style="height: 50px;">
<div class="block2">block2</div>
</div>
</article>
</html>

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>CSS Multi-column Layout Test: Test a multi-column container with percentage height children</title>
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
<link rel="match" href="multicol-span-all-children-height-002-ref.html">
<meta name="assert" content="This test checks the percentage height children under multicol container compute the percentage relative to the entire multicol, not just the part after the column-span.">
<style>
article {
column-count: 2;
width: 400px;
height: 200px;
background-color: lightgreen;
border: 5px solid purple;
}
div.block1 {
background-color: yellow;
height: 100%; /* Spread evenly into two columns, each 100px. */
}
div.spanner {
column-span: all;
height: 25%;
background-color: lightblue;
}
div.block2 {
background-color: yellow;
/* Column container has only 25% height left, so two extra overflow columns
are created. Total 4 columns, each 50px. */
height: 100%;
}
</style>
<article>
<div class="block1">block1</div>
<div class="spanner">spanner</div>
<div class="block2">block2</div>
</article>
</html>

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>CSS Multi-column Layout Test Reference: Test a multi-column container with percentage height children</title>
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<style>
article {
width: 400px;
height: 200px;
background-color: lightgreen;
border: 5px solid purple;
}
div.columns {
column-count: 2;
}
div.block1 {
background-color: yellow;
height: 600px;
}
div.spanner {
height: 50px;
background-color: lightblue;
}
div.block2 {
background-color: yellow;
height: 200px;
}
</style>
<article>
<div class="columns" style="height: 200px;">
<div class="block1">block1</div>
</div>
<div class="spanner">spanner</div>
<div class="columns" style="height: 1px;">
<div class="block2">block2</div>
</div>
</article>
</html>

Просмотреть файл

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>CSS Multi-column Layout Test: Test a multi-column container with percentage height children</title>
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
<link rel="help" href="https://drafts.csswg.org/css-break/#breaking-rules">
<link rel="match" href="multicol-span-all-children-height-003-ref.html">
<meta name="assert" content="This test checks the percentage height children under multicol container compute the percentage relative to the entire multicol, not just the part after the column-span.">
<style>
article {
column-count: 2;
width: 400px;
height: 200px;
background-color: lightgreen;
border: 5px solid purple;
}
div.block1 {
background-color: yellow;
/* This overflows the column container, so one extra column is created. */
height: 300%;
}
div.spanner {
column-span: all;
height: 25%;
background-color: lightblue;
}
div.block2 {
background-color: yellow;
/* No height left for this block. According to the breaking rules, the
column container creates 1px column boxes for it. */
height: 100%;
}
</style>
<article>
<div class="block1">block1</div>
<div class="spanner">spanner</div>
<div class="block2">block2</div>
</article>
</html>