mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1504053 - Reframe multi-column container if inserting a subtree with a column-span child. r=dbaron
Differential Revision: https://phabricator.services.mozilla.com/D16077 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6df4e561ff
commit
5ec0177dc3
@ -5932,7 +5932,7 @@ void nsCSSFrameConstructor::AppendFramesToParent(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're appending a list of frames at the last continuations of a
|
// If we're appending a list of frames to the last continuations of a
|
||||||
// ::-moz-column-content, we may need to create column-span siblings for them.
|
// ::-moz-column-content, we may need to create column-span siblings for them.
|
||||||
if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
|
if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
|
||||||
// Extract any initial non-column-span kids, and append them to
|
// Extract any initial non-column-span kids, and append them to
|
||||||
@ -6871,6 +6871,14 @@ void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
|
|||||||
AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
|
AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LAYOUT_PHASE_TEMP_EXIT();
|
||||||
|
if (StaticPrefs::layout_css_column_span_enabled() &&
|
||||||
|
MaybeRecreateForColumnSpan(state, parentFrame, frameItems, prevSibling)) {
|
||||||
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
|
|
||||||
if (frameItems.NotEmpty()) { // append the in-flow kids
|
if (frameItems.NotEmpty()) { // append the in-flow kids
|
||||||
AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
|
AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
|
||||||
}
|
}
|
||||||
@ -7326,6 +7334,15 @@ void nsCSSFrameConstructor::ContentRangeInserted(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LAYOUT_PHASE_TEMP_EXIT();
|
||||||
|
if (StaticPrefs::layout_css_column_span_enabled() &&
|
||||||
|
MaybeRecreateForColumnSpan(state, insertion.mParentFrame, frameItems,
|
||||||
|
prevSibling)) {
|
||||||
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
|
|
||||||
if (frameItems.NotEmpty()) {
|
if (frameItems.NotEmpty()) {
|
||||||
// Notify the parent frame
|
// Notify the parent frame
|
||||||
if (isAppend) {
|
if (isAppend) {
|
||||||
@ -10857,6 +10874,61 @@ nsFrameItems nsCSSFrameConstructor::CreateColumnSpanSiblings(
|
|||||||
return siblings;
|
return siblings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nsCSSFrameConstructor::MaybeRecreateForColumnSpan(
|
||||||
|
nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
|
||||||
|
nsFrameList& aFrameList, nsIFrame* aPrevSibling) {
|
||||||
|
MOZ_ASSERT(StaticPrefs::layout_css_column_span_enabled(),
|
||||||
|
"Call this only when layout.css.column-span.enabled is true!");
|
||||||
|
|
||||||
|
if (!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!IsFramePartOfIBSplit(aParentFrame),
|
||||||
|
"We should have wiped aParentFrame in WipeContainingBlock if it's "
|
||||||
|
"part of IB split!");
|
||||||
|
|
||||||
|
nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
|
||||||
|
if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
|
||||||
|
// We are appending a list of frames to the last continuation of a
|
||||||
|
// ::-moz-column-content. This is the case where we can fix the frame tree
|
||||||
|
// instead of reframing the containing block. Return false and let
|
||||||
|
// AppendFramesToParent() deal with this.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto HasColumnSpan = [](const nsFrameList& aList) {
|
||||||
|
for (nsIFrame* f : aList) {
|
||||||
|
if (f->IsColumnSpan()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (HasColumnSpan(aFrameList)) {
|
||||||
|
// If any frame in the frame list has "column-span:all" style, i.e. a
|
||||||
|
// -moz-column-span-wrapper frame, we need to reframe the multi-column
|
||||||
|
// containing block.
|
||||||
|
//
|
||||||
|
// We can only be here if none of the new inserted nsIContent* nodes (via
|
||||||
|
// ContentAppended or ContentRangeInserted) have column-span:all style, yet
|
||||||
|
// some of them have column-span:all descendants. Sadly, there's no way to
|
||||||
|
// detect this by checking FrameConstructionItems in WipeContainingBlock().
|
||||||
|
// Otherwise, we would have already wiped the multi-column containing block.
|
||||||
|
PROFILER_TRACING("Layout",
|
||||||
|
"Reframe multi-column after constructing frame list",
|
||||||
|
LAYOUT, TRACING_EVENT);
|
||||||
|
aFrameList.DestroyFrames();
|
||||||
|
RecreateFramesForContent(
|
||||||
|
GetMultiColumnContainingBlockFor(aParentFrame)->GetContent(),
|
||||||
|
InsertionKind::Async);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
nsIFrame* nsCSSFrameConstructor::ConstructInline(
|
nsIFrame* nsCSSFrameConstructor::ConstructInline(
|
||||||
nsFrameConstructorState& aState, FrameConstructionItem& aItem,
|
nsFrameConstructorState& aState, FrameConstructionItem& aItem,
|
||||||
nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
|
nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
|
||||||
|
@ -1891,6 +1891,23 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
nsFrameList& aChildList,
|
nsFrameList& aChildList,
|
||||||
nsIFrame* aPositionedFrame);
|
nsIFrame* aPositionedFrame);
|
||||||
|
|
||||||
|
// Reconstruct the multi-column containing block of aParentFrame when we want
|
||||||
|
// to insert aFrameList into aParentFrame immediately after aPrevSibling but
|
||||||
|
// cannot fix the frame tree because aFrameList contains some column-spans.
|
||||||
|
//
|
||||||
|
// @param aParentFrame the to-be parent frame for aFrameList.
|
||||||
|
// @param aFrameList the frames to be inserted. It will be cleared if we need
|
||||||
|
// reconstruction.
|
||||||
|
// @param aPrevSibling the position where the frames in aFrameList are going
|
||||||
|
// to be inserted. Nullptr means aFrameList is being inserted at
|
||||||
|
// the beginning.
|
||||||
|
// @return true if the multi-column containing block of aParentFrame is
|
||||||
|
// reconstructed; false otherwise.
|
||||||
|
bool MaybeRecreateForColumnSpan(nsFrameConstructorState& aState,
|
||||||
|
nsContainerFrame* aParentFrame,
|
||||||
|
nsFrameList& aFrameList,
|
||||||
|
nsIFrame* aPrevSibling);
|
||||||
|
|
||||||
nsIFrame* ConstructInline(nsFrameConstructorState& aState,
|
nsIFrame* ConstructInline(nsFrameConstructorState& aState,
|
||||||
FrameConstructionItem& aItem,
|
FrameConstructionItem& aItem,
|
||||||
nsContainerFrame* aParentFrame,
|
nsContainerFrame* aParentFrame,
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
[multicol-span-all-dynamic-add-011.html]
|
||||||
|
prefs: [layout.css.column-span.enabled:true]
|
@ -0,0 +1,2 @@
|
|||||||
|
[multicol-span-all-dynamic-add-012.html]
|
||||||
|
prefs: [layout.css.column-span.enabled:true]
|
@ -0,0 +1,55 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Multi-column Layout Test: Insert a block containing a spanner kid. The spanner kid should correctly span across all columns</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-dynamic-add-003-ref.html">
|
||||||
|
<meta name="assert" content="This test checks that an inserted block containing 'column-span' element should be rendered correctly.">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function runTest() {
|
||||||
|
document.body.offsetHeight;
|
||||||
|
|
||||||
|
// Create a subtree like the following, and insert it into column as the
|
||||||
|
// first child.
|
||||||
|
// <div>
|
||||||
|
// block1
|
||||||
|
// <h3>spanner</h3>
|
||||||
|
// </div>
|
||||||
|
var spanner = document.createElement("h3");
|
||||||
|
var spannerText = document.createTextNode("spanner");
|
||||||
|
spanner.appendChild(spannerText);
|
||||||
|
|
||||||
|
var block1 = document.createElement("div");
|
||||||
|
var block1Text = document.createTextNode("block1");
|
||||||
|
block1.appendChild(block1Text)
|
||||||
|
block1.appendChild(spanner);
|
||||||
|
|
||||||
|
var column = document.getElementById("column");
|
||||||
|
column.insertBefore(block1, column.children[0]);
|
||||||
|
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#column {
|
||||||
|
column-count: 3;
|
||||||
|
column-rule: 6px solid;
|
||||||
|
width: 400px;
|
||||||
|
outline: 1px solid black;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
column-span: all;
|
||||||
|
outline: 1px solid blue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body onload="runTest();">
|
||||||
|
<article id="column">
|
||||||
|
<div>block2</div>
|
||||||
|
</article>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Multi-column Layout Test Reference: Append a block containing a spanner kid. The spanner kid should correctly span across all columns</title>
|
||||||
|
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#column {
|
||||||
|
column-count: 3;
|
||||||
|
column-rule: 6px solid;
|
||||||
|
width: 400px;
|
||||||
|
outline: 1px solid black;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
column-span: all;
|
||||||
|
outline: 1px solid blue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<article id="column">
|
||||||
|
<div>block1
|
||||||
|
<div>
|
||||||
|
<h3>spanner</h3>
|
||||||
|
block2
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,54 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Multi-column Layout Test: Append a block containing a spanner kid. The spanner kid should correctly span across all columns</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-dynamic-add-012-ref.html">
|
||||||
|
<meta name="assert" content="This test checks that an appended block containing 'column-span' element should be rendered correctly.">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function runTest() {
|
||||||
|
document.body.offsetHeight;
|
||||||
|
|
||||||
|
// Create a subtree like the following, and append it to block1.
|
||||||
|
// <div>
|
||||||
|
// <h3>spanner</h3>
|
||||||
|
// block2
|
||||||
|
// </div>
|
||||||
|
var spanner = document.createElement("h3");
|
||||||
|
var spannerText = document.createTextNode("spanner");
|
||||||
|
spanner.appendChild(spannerText);
|
||||||
|
|
||||||
|
var block2 = document.createElement("div");
|
||||||
|
var block2Text = document.createTextNode("block2");
|
||||||
|
block2.appendChild(spanner);
|
||||||
|
block2.appendChild(block2Text)
|
||||||
|
|
||||||
|
var block1 = document.getElementById("block1");
|
||||||
|
block1.appendChild(block2);
|
||||||
|
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#column {
|
||||||
|
column-count: 3;
|
||||||
|
column-rule: 6px solid;
|
||||||
|
width: 400px;
|
||||||
|
outline: 1px solid black;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
column-span: all;
|
||||||
|
outline: 1px solid blue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body onload="runTest();">
|
||||||
|
<article id="column">
|
||||||
|
<div id="block1">block1</div>
|
||||||
|
</article>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user