Bug 1565136 - Move some reframing logic out of WipeContainingBlock to make it done earlier. r=dholbert
Also move the duplicate logic for reframing MathML in ContentAppended() and ContentRangeInserted() into WipeInsertionParent(). Differential Revision: https://phabricator.services.mozilla.com/D38417
This commit is contained in:
@@ -6761,12 +6761,12 @@ void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
|
|
||||||
LAYOUT_PHASE_TEMP_EXIT();
|
LAYOUT_PHASE_TEMP_EXIT();
|
||||||
RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
|
if (WipeInsertionParent(parentFrame)) {
|
||||||
LAYOUT_PHASE_TEMP_REENTER();
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (gNoisyContentUpdates && IsFramePartOfIBSplit(parentFrame)) {
|
if (gNoisyContentUpdates && IsFramePartOfIBSplit(parentFrame)) {
|
||||||
@@ -7162,15 +7162,12 @@ void nsCSSFrameConstructor::ContentRangeInserted(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(emilio): This looks terribly inefficient if you insert elements deep
|
|
||||||
// in a MathML subtree.
|
|
||||||
if (insertion.mParentFrame->IsFrameOfType(nsIFrame::eMathML)) {
|
|
||||||
LAYOUT_PHASE_TEMP_EXIT();
|
LAYOUT_PHASE_TEMP_EXIT();
|
||||||
RecreateFramesForContent(insertion.mParentFrame->GetContent(),
|
if (WipeInsertionParent(insertion.mParentFrame)) {
|
||||||
InsertionKind::Async);
|
|
||||||
LAYOUT_PHASE_TEMP_REENTER();
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
LAYOUT_PHASE_TEMP_REENTER();
|
||||||
|
|
||||||
nsFrameConstructorState state(
|
nsFrameConstructorState state(
|
||||||
mPresShell, GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
|
mPresShell, GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
|
||||||
@@ -11283,6 +11280,64 @@ static bool IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
|
||||||
|
#define TRACE(reason) \
|
||||||
|
PROFILER_TRACING("Layout", "WipeInsertionParent: " reason, LAYOUT, \
|
||||||
|
TRACING_EVENT)
|
||||||
|
|
||||||
|
const LayoutFrameType frameType = aFrame->Type();
|
||||||
|
|
||||||
|
// FIXME(emilio): This looks terribly inefficient if you insert elements deep
|
||||||
|
// in a MathML subtree.
|
||||||
|
if (aFrame->IsFrameOfType(nsIFrame::eMathML)) {
|
||||||
|
TRACE("MathML");
|
||||||
|
RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ruby-related frame that's getting new children.
|
||||||
|
// The situation for ruby is complex, especially when interacting with
|
||||||
|
// spaces. It contains these two special cases apart from tables:
|
||||||
|
// 1) There are effectively three types of white spaces in ruby frames
|
||||||
|
// we handle differently: leading/tailing/inter-level space,
|
||||||
|
// inter-base/inter-annotation space, and inter-segment space.
|
||||||
|
// These three types of spaces can be converted to each other when
|
||||||
|
// their sibling changes.
|
||||||
|
// 2) The first effective child of a ruby frame must always be a ruby
|
||||||
|
// base container. It should be created or destroyed accordingly.
|
||||||
|
if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
|
||||||
|
RubyUtils::IsRubyContainerBox(frameType)) {
|
||||||
|
// We want to optimize it better, and avoid reframing as much as
|
||||||
|
// possible. But given the cases above, and the fact that a ruby
|
||||||
|
// usually won't be very large, it should be fine to reframe it.
|
||||||
|
TRACE("Ruby");
|
||||||
|
RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A <details> that's getting new children. When inserting
|
||||||
|
// elements into <details>, we reframe the <details> and let frame constructor
|
||||||
|
// move the main <summary> to the front when constructing the frame
|
||||||
|
// construction items.
|
||||||
|
if (aFrame->IsDetailsFrame()) {
|
||||||
|
TRACE("Details / Summary");
|
||||||
|
RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reframe the multi-column container whenever elements insert/append
|
||||||
|
// into it because we need to reconstruct column-span split.
|
||||||
|
if (aFrame->IsColumnSetWrapperFrame()) {
|
||||||
|
TRACE("Multi-column");
|
||||||
|
RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#undef TRACE
|
||||||
|
}
|
||||||
|
|
||||||
bool nsCSSFrameConstructor::WipeContainingBlock(
|
bool nsCSSFrameConstructor::WipeContainingBlock(
|
||||||
nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
|
nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
|
||||||
nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
|
nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
|
||||||
@@ -11374,27 +11429,7 @@ bool nsCSSFrameConstructor::WipeContainingBlock(
|
|||||||
// an anonymous flex or grid item. That's where it's already going - good!
|
// an anonymous flex or grid item. That's where it's already going - good!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Situation #4 is a ruby-related frame that's getting new children.
|
// Situation #4 is a case when table pseudo-frames don't work out right
|
||||||
// The situation for ruby is complex, especially when interacting with
|
|
||||||
// spaces. It contains these two special cases apart from tables:
|
|
||||||
// 1) There are effectively three types of white spaces in ruby frames
|
|
||||||
// we handle differently: leading/tailing/inter-level space,
|
|
||||||
// inter-base/inter-annotation space, and inter-segment space.
|
|
||||||
// These three types of spaces can be converted to each other when
|
|
||||||
// their sibling changes.
|
|
||||||
// 2) The first effective child of a ruby frame must always be a ruby
|
|
||||||
// base container. It should be created or destroyed accordingly.
|
|
||||||
if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
|
|
||||||
RubyUtils::IsRubyContainerBox(frameType)) {
|
|
||||||
// We want to optimize it better, and avoid reframing as much as
|
|
||||||
// possible. But given the cases above, and the fact that a ruby
|
|
||||||
// usually won't be very large, it should be fine to reframe it.
|
|
||||||
TRACE("Ruby");
|
|
||||||
RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Situation #5 is a case when table pseudo-frames don't work out right
|
|
||||||
ParentType parentType = GetParentType(aFrame);
|
ParentType parentType = GetParentType(aFrame);
|
||||||
// If all the kids want a parent of the type that aFrame is, then we're all
|
// If all the kids want a parent of the type that aFrame is, then we're all
|
||||||
// set to go. Indeed, there won't be any table pseudo-frames created between
|
// set to go. Indeed, there won't be any table pseudo-frames created between
|
||||||
@@ -11563,25 +11598,7 @@ bool nsCSSFrameConstructor::WipeContainingBlock(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Situation #6 is a <details> that's getting new children. When inserting
|
// Situation #5 is a frame in multicol subtree that's getting new children.
|
||||||
// elements into <details>, we reframe the <details> and let frame constructor
|
|
||||||
// move the main <summary> to the front when constructing the frame
|
|
||||||
// construction items.
|
|
||||||
if (aFrame->IsDetailsFrame()) {
|
|
||||||
TRACE("Details / Summary");
|
|
||||||
RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Situation #7 is a column hierarchy that's getting new children.
|
|
||||||
if (aFrame->IsColumnSetWrapperFrame()) {
|
|
||||||
// Reframe the multi-column container whenever elements insert/append
|
|
||||||
// into it.
|
|
||||||
TRACE("Multi-column");
|
|
||||||
RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
|
if (aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
|
||||||
MOZ_ASSERT(!aFrame->IsDetailsFrame(),
|
MOZ_ASSERT(!aFrame->IsDetailsFrame(),
|
||||||
"Inserting elements into <details> should have been reframed!");
|
"Inserting elements into <details> should have been reframed!");
|
||||||
|
|||||||
@@ -1909,6 +1909,19 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
bool aItemIsWithinSVGText,
|
bool aItemIsWithinSVGText,
|
||||||
bool aItemAllowsTextPathChild);
|
bool aItemAllowsTextPathChild);
|
||||||
|
|
||||||
|
// Determine whether we need to wipe out aFrame (the insertion parent) and
|
||||||
|
// rebuild the entire subtree when we insert or append new content under
|
||||||
|
// aFrame.
|
||||||
|
//
|
||||||
|
// This is similar to WipeContainingBlock(), but is called before constructing
|
||||||
|
// any frame construction items. Any container frames which need reframing
|
||||||
|
// regardless of the content inserted or appended can add a check in this
|
||||||
|
// method.
|
||||||
|
//
|
||||||
|
// @return true if we reconstructed the insertion parent frame; false
|
||||||
|
// otherwise
|
||||||
|
bool WipeInsertionParent(nsContainerFrame* aFrame);
|
||||||
|
|
||||||
// Determine whether we need to wipe out what we just did and start over
|
// Determine whether we need to wipe out what we just did and start over
|
||||||
// because we're doing something like adding block kids to an inline frame
|
// because we're doing something like adding block kids to an inline frame
|
||||||
// (and therefore need an {ib} split). aPrevSibling must be correct, even in
|
// (and therefore need an {ib} split). aPrevSibling must be correct, even in
|
||||||
|
|||||||
Reference in New Issue
Block a user