Bug 1874823 - Remove NS_BLOCK_STATIC_BFC and NS_BLOCK_CLIP_PAGINATED_OVERFLOW. r=fredw
Put all the "is this block a BFC" logic in nsBlockFrame.cpp. The CLIP_PAGINATED_OVERFLOW flag is also redundant, it can just be "has non-propagated overflow styles" check in ShouldApplyOverflowClipping(), and frees another bit. Shouldn't change behavior. Differential Revision: https://phabricator.services.mozilla.com/D203590
This commit is contained in:
@@ -321,7 +321,7 @@ static bool ShouldSuppressColumnSpanDescendants(nsIFrame* aFrame) {
|
||||
}
|
||||
|
||||
if (!aFrame->IsBlockFrameOrSubclass() ||
|
||||
aFrame->HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS | NS_FRAME_OUT_OF_FLOW) ||
|
||||
aFrame->HasAnyStateBits(NS_BLOCK_BFC | NS_FRAME_OUT_OF_FLOW) ||
|
||||
aFrame->IsFixedPosContainingBlock()) {
|
||||
// Need to suppress column-span if we:
|
||||
// - Are a different block formatting context,
|
||||
@@ -2287,7 +2287,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructTableCell(
|
||||
aState, content, innerPseudoStyle, cellFrame,
|
||||
PseudoStyleType::scrolledContent, false, scrollFrame);
|
||||
}
|
||||
cellInnerFrame = NS_NewBlockFormattingContext(mPresShell, innerPseudoStyle);
|
||||
cellInnerFrame = NS_NewBlockFrame(mPresShell, innerPseudoStyle);
|
||||
}
|
||||
auto* parent = scrollFrame ? scrollFrame : cellFrame;
|
||||
InitAndRestoreFrame(aState, content, parent, cellInnerFrame);
|
||||
@@ -2567,7 +2567,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
|
||||
MOZ_ASSERT(display->mDisplay == StyleDisplay::Block ||
|
||||
display->mDisplay == StyleDisplay::FlowRoot,
|
||||
"Unhandled display type for root element");
|
||||
contentFrame = NS_NewBlockFormattingContext(mPresShell, computedStyle);
|
||||
contentFrame = NS_NewBlockFrame(mPresShell, computedStyle);
|
||||
ConstructBlock(
|
||||
state, aDocElement,
|
||||
state.GetGeometricParent(*display, mDocElementContainingBlock),
|
||||
@@ -3147,8 +3147,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
|
||||
MOZ_ASSERT(fieldsetContentDisplay->mDisplay == StyleDisplay::Block,
|
||||
"bug in StyleAdjuster::adjust_for_fieldset_content?");
|
||||
|
||||
contentFrame =
|
||||
NS_NewBlockFormattingContext(mPresShell, fieldsetContentStyle);
|
||||
contentFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle);
|
||||
if (fieldsetContentStyle->StyleColumn()->IsColumnContainerStyle()) {
|
||||
contentFrameTop = BeginBuildingColumns(
|
||||
aState, content, parent, contentFrame, fieldsetContentStyle);
|
||||
@@ -3691,11 +3690,6 @@ void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
|
||||
CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS,
|
||||
FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
|
||||
#undef CHECK_ONLY_ONE_BIT
|
||||
NS_ASSERTION(!(bits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) ||
|
||||
((bits & FCDATA_FUNC_IS_FULL_CTOR) &&
|
||||
data->mFunc.mFullConstructor ==
|
||||
&nsCSSFrameConstructor::ConstructNonScrollableBlock),
|
||||
"Unexpected FCDATA_FORCED_NON_SCROLLABLE_BLOCK flag");
|
||||
MOZ_ASSERT(
|
||||
!(bits & FCDATA_IS_WRAPPER_ANON_BOX) || (bits & FCDATA_USE_CHILD_ITEMS),
|
||||
"Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS");
|
||||
@@ -3773,7 +3767,7 @@ void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
|
||||
innerFrame = outerFrame;
|
||||
break;
|
||||
default: {
|
||||
innerFrame = NS_NewBlockFormattingContext(mPresShell, outerStyle);
|
||||
innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
|
||||
if (outerStyle->StyleColumn()->IsColumnContainerStyle()) {
|
||||
outerFrame = BeginBuildingColumns(aState, content, container,
|
||||
innerFrame, outerStyle);
|
||||
@@ -3786,7 +3780,7 @@ void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
innerFrame = NS_NewBlockFormattingContext(mPresShell, outerStyle);
|
||||
innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
|
||||
InitAndRestoreFrame(aState, content, container, innerFrame);
|
||||
outerFrame = innerFrame;
|
||||
}
|
||||
@@ -4336,14 +4330,14 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
|
||||
// XXX Ignore tables for the time being (except caption)
|
||||
const uint32_t kCaptionCtorFlags =
|
||||
FCDATA_IS_TABLE_PART | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable);
|
||||
bool caption = aDisplay.mDisplay == StyleDisplay::TableCaption;
|
||||
bool suppressScrollFrame = false;
|
||||
bool needScrollFrame =
|
||||
const bool caption = aDisplay.mDisplay == StyleDisplay::TableCaption;
|
||||
const bool needScrollFrame =
|
||||
aDisplay.IsScrollableOverflow() && !propagatedScrollToViewport;
|
||||
if (needScrollFrame) {
|
||||
suppressScrollFrame = mPresShell->GetPresContext()->IsPaginated() &&
|
||||
aDisplay.IsBlockOutsideStyle() &&
|
||||
!aElement.IsInNativeAnonymousSubtree();
|
||||
const bool suppressScrollFrame =
|
||||
mPresShell->GetPresContext()->IsPaginated() &&
|
||||
aDisplay.IsBlockOutsideStyle() &&
|
||||
!aElement.IsInNativeAnonymousSubtree();
|
||||
if (!suppressScrollFrame) {
|
||||
static constexpr FrameConstructionData sScrollableBlockData[2] = {
|
||||
{&nsCSSFrameConstructor::ConstructScrollableBlock},
|
||||
@@ -4351,27 +4345,14 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
|
||||
kCaptionCtorFlags}};
|
||||
return &sScrollableBlockData[caption];
|
||||
}
|
||||
|
||||
// If the scrollable frame would have propagated its scrolling to the
|
||||
// viewport, we still want to construct a regular block rather than a
|
||||
// scrollframe so that it paginates correctly, but we don't want to set
|
||||
// the bit on the block that tells it to clip at paint time.
|
||||
if (mPresShell->GetPresContext()->ElementWouldPropagateScrollStyles(
|
||||
aElement)) {
|
||||
suppressScrollFrame = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle various non-scrollable blocks.
|
||||
static constexpr FrameConstructionData sNonScrollableBlockData[2][2] = {
|
||||
{{&nsCSSFrameConstructor::ConstructNonScrollableBlock},
|
||||
{&nsCSSFrameConstructor::ConstructNonScrollableBlock,
|
||||
kCaptionCtorFlags}},
|
||||
{{&nsCSSFrameConstructor::ConstructNonScrollableBlock,
|
||||
FCDATA_FORCED_NON_SCROLLABLE_BLOCK},
|
||||
{&nsCSSFrameConstructor::ConstructNonScrollableBlock,
|
||||
FCDATA_FORCED_NON_SCROLLABLE_BLOCK | kCaptionCtorFlags}}};
|
||||
return &sNonScrollableBlockData[suppressScrollFrame][caption];
|
||||
static constexpr FrameConstructionData sNonScrollableBlockData[2] = {
|
||||
{&nsCSSFrameConstructor::ConstructNonScrollableBlock},
|
||||
{&nsCSSFrameConstructor::ConstructNonScrollableBlock,
|
||||
kCaptionCtorFlags}};
|
||||
return &sNonScrollableBlockData[caption];
|
||||
}
|
||||
case StyleDisplayInside::Table: {
|
||||
static constexpr FrameConstructionData data(
|
||||
@@ -4505,8 +4486,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructScrollableBlock(
|
||||
|
||||
// Create our block frame
|
||||
// pass a temporary stylecontext, the correct one will be set later
|
||||
nsContainerFrame* scrolledFrame =
|
||||
NS_NewBlockFormattingContext(mPresShell, computedStyle);
|
||||
nsContainerFrame* scrolledFrame = NS_NewBlockFrame(mPresShell, computedStyle);
|
||||
|
||||
// Make sure to AddChild before we call ConstructBlock so that we
|
||||
// end up before our descendants in fixed-pos lists as needed.
|
||||
@@ -4529,26 +4509,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructNonScrollableBlock(
|
||||
nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
|
||||
nsFrameList& aFrameList) {
|
||||
ComputedStyle* const computedStyle = aItem.mComputedStyle;
|
||||
|
||||
// We want a block formatting context root in paginated contexts for
|
||||
// every block that would be scrollable in a non-paginated context.
|
||||
// We mark our blocks with a bit here if this condition is true, so
|
||||
// we can check it later in nsIFrame::ApplyPaginatedOverflowClipping.
|
||||
bool clipPaginatedOverflow =
|
||||
(aItem.mFCData->mBits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) != 0;
|
||||
nsFrameState flags = nsFrameState(0);
|
||||
if ((aDisplay->IsAbsolutelyPositionedStyle() || aDisplay->IsFloatingStyle() ||
|
||||
aDisplay->DisplayInside() == StyleDisplayInside::FlowRoot ||
|
||||
clipPaginatedOverflow) &&
|
||||
!aParentFrame->IsInSVGTextSubtree()) {
|
||||
flags = NS_BLOCK_STATIC_BFC;
|
||||
if (clipPaginatedOverflow) {
|
||||
flags |= NS_BLOCK_CLIP_PAGINATED_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
nsContainerFrame* newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
|
||||
newFrame->AddStateBits(flags);
|
||||
ConstructBlock(aState, aItem.mContent,
|
||||
aState.GetGeometricParent(*aDisplay, aParentFrame),
|
||||
aParentFrame, computedStyle, &newFrame, aFrameList,
|
||||
@@ -8707,15 +8668,14 @@ void nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
|
||||
mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
|
||||
PseudoStyleType::anonymousItem, aParentFrame->Style());
|
||||
|
||||
static constexpr FrameConstructionData sBlockFormattingContextFCData(
|
||||
ToCreationFunc(NS_NewBlockFormattingContext),
|
||||
FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS |
|
||||
FCDATA_IS_WRAPPER_ANON_BOX);
|
||||
static constexpr FrameConstructionData sBlockFCData(
|
||||
ToCreationFunc(NS_NewBlockFrame), FCDATA_SKIP_FRAMESET |
|
||||
FCDATA_USE_CHILD_ITEMS |
|
||||
FCDATA_IS_WRAPPER_ANON_BOX);
|
||||
|
||||
FrameConstructionItem* newItem = new (this)
|
||||
FrameConstructionItem(&sBlockFormattingContextFCData,
|
||||
// Use the content of our parent frame
|
||||
parentContent, wrapperStyle.forget(), true);
|
||||
// Use the content of our parent frame
|
||||
auto* newItem = new (this) FrameConstructionItem(
|
||||
&sBlockFCData, parentContent, wrapperStyle.forget(), true);
|
||||
|
||||
newItem->mIsAllInline =
|
||||
newItem->mComputedStyle->StyleDisplay()->IsInlineOutsideStyle();
|
||||
|
||||
@@ -723,10 +723,6 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
||||
This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
|
||||
The child items might still need table pseudo processing. */
|
||||
#define FCDATA_USE_CHILD_ITEMS 0x10000
|
||||
/* If FCDATA_FORCED_NON_SCROLLABLE_BLOCK is set, then this block
|
||||
would have been scrollable but has been forced to be
|
||||
non-scrollable due to being in a paginated context. */
|
||||
#define FCDATA_FORCED_NON_SCROLLABLE_BLOCK 0x20000
|
||||
/* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a
|
||||
block formatting context wrapper around the kids of this frame
|
||||
using the FrameConstructionData's mPseudoAtom for its anonymous
|
||||
|
||||
@@ -785,11 +785,6 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
||||
void nsFieldSetFrame::SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList&& aChildList) {
|
||||
nsContainerFrame::SetInitialChildList(aListID, std::move(aChildList));
|
||||
if (nsBlockFrame* legend = do_QueryFrame(GetLegend())) {
|
||||
// A rendered legend always establish a new formatting context.
|
||||
// https://html.spec.whatwg.org/multipage/rendering.html#rendered-legend
|
||||
legend->AddStateBits(NS_BLOCK_STATIC_BFC);
|
||||
}
|
||||
MOZ_ASSERT(
|
||||
aListID != FrameChildListID::Principal || GetInner() || GetLegend(),
|
||||
"Setting principal child list should populate our inner frame "
|
||||
@@ -816,11 +811,6 @@ void nsFieldSetFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
|
||||
nsContainerFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine,
|
||||
std::move(aFrameList));
|
||||
MOZ_ASSERT(GetLegend());
|
||||
if (nsBlockFrame* legend = do_QueryFrame(GetLegend())) {
|
||||
// A rendered legend always establish a new formatting context.
|
||||
// https://html.spec.whatwg.org/multipage/rendering.html#rendered-legend
|
||||
legend->AddStateBits(NS_BLOCK_STATIC_BFC);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -41,16 +41,16 @@ class BlockReflowState {
|
||||
mCanHaveOverflowMarkers(false) {}
|
||||
|
||||
// Set in the BlockReflowState constructor when reflowing a "block margin
|
||||
// root" frame (i.e. a frame with any of the NS_BLOCK_BFC_STATE_BITS flag
|
||||
// set, for which margins apply by default).
|
||||
// root" frame (i.e. a frame with any of the NS_BLOCK_BFC flag set, for
|
||||
// which margins apply by default).
|
||||
//
|
||||
// The flag is also set when reflowing a frame whose computed BStart border
|
||||
// padding is non-zero.
|
||||
bool mIsBStartMarginRoot : 1;
|
||||
|
||||
// Set in the BlockReflowState constructor when reflowing a "block margin
|
||||
// root" frame (i.e. a frame with any of the NS_BLOCK_BFC_STATE_BITS flag
|
||||
// set, for which margins apply by default).
|
||||
// root" frame (i.e. a frame with any of the NS_BLOCK_BFC flag set, for
|
||||
// which margins apply by default).
|
||||
//
|
||||
// The flag is also set when reflowing a frame whose computed BEnd border
|
||||
// padding is non-zero.
|
||||
|
||||
@@ -14,6 +14,7 @@ COMMON = {
|
||||
LEAF = {"Leaf"}
|
||||
MATHML = {"MathML"}
|
||||
SVG = {"SVG"}
|
||||
BFC = {"BlockFormattingContext"}
|
||||
|
||||
BLOCK = COMMON | {"CanContainOverflowContainers"}
|
||||
|
||||
@@ -54,13 +55,13 @@ FRAME_CLASSES = [
|
||||
Frame("nsCheckboxRadioFrame", "CheckboxRadio", REPLACED_WITH_BLOCK | LEAF),
|
||||
Frame("nsColorControlFrame", "ColorControl", REPLACED_WITH_BLOCK | LEAF),
|
||||
Frame("nsColumnSetFrame", "ColumnSet", COMMON),
|
||||
Frame("ColumnSetWrapperFrame", "ColumnSetWrapper", BLOCK),
|
||||
Frame("ColumnSetWrapperFrame", "ColumnSetWrapper", BLOCK | BFC),
|
||||
Frame("nsComboboxControlFrame", "ComboboxControl", REPLACED_WITH_BLOCK | LEAF),
|
||||
Frame("ComboboxLabelFrame", "Block", BLOCK),
|
||||
Frame("nsContinuingTextFrame", "Text", TEXT),
|
||||
Frame("nsDateTimeControlFrame", "DateTimeControl", REPLACED_WITH_BLOCK),
|
||||
Frame("nsFieldSetFrame", "FieldSet", BLOCK),
|
||||
Frame("nsFileControlFrame", "Block", REPLACED_WITH_BLOCK | LEAF),
|
||||
Frame("nsFileControlFrame", "Block", REPLACED_WITH_BLOCK | LEAF | BFC),
|
||||
Frame("FileControlLabelFrame", "Block", BLOCK | LEAF),
|
||||
Frame("nsFirstLetterFrame", "Letter", INLINE),
|
||||
Frame("nsFloatingFirstLetterFrame", "Letter", INLINE - {"LineParticipant"}),
|
||||
@@ -79,7 +80,7 @@ FRAME_CLASSES = [
|
||||
Frame("nsImageFrame", "Image", REPLACED_SIZING | {"LeafDynamic"}),
|
||||
Frame("nsInlineFrame", "Inline", INLINE),
|
||||
Frame("nsListControlFrame", "ListControl", REPLACED_WITH_BLOCK),
|
||||
Frame("nsMathMLmathBlockFrame", "Block", BLOCK | MATHML),
|
||||
Frame("nsMathMLmathBlockFrame", "Block", BLOCK | MATHML | BFC),
|
||||
Frame("nsMathMLmathInlineFrame", "Inline", INLINE | MATHML),
|
||||
Frame("nsMathMLmencloseFrame", "None", MATHML_CONTAINER),
|
||||
Frame("nsMathMLmfracFrame", "None", MATHML_CONTAINER),
|
||||
@@ -115,7 +116,7 @@ FRAME_CLASSES = [
|
||||
Frame("nsScrollbarButtonFrame", "SimpleXULLeaf", COMMON | LEAF),
|
||||
Frame("nsScrollbarFrame", "Scrollbar", COMMON),
|
||||
Frame("nsSearchControlFrame", "SearchControl", LEAF),
|
||||
Frame("nsSelectsAreaFrame", "Block", BLOCK),
|
||||
Frame("nsSelectsAreaFrame", "Block", BLOCK | BFC),
|
||||
Frame("nsPageSequenceFrame", "PageSequence", COMMON),
|
||||
Frame("nsSliderFrame", "Slider", COMMON),
|
||||
Frame("nsSplitterFrame", "SimpleXULLeaf", COMMON | LEAF),
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "nsPresContextInlines.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "prenv.h"
|
||||
@@ -50,22 +49,15 @@
|
||||
#include <algorithm>
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsCSSAnonBoxes.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "TextOverflow.h"
|
||||
#include "nsIFrameInlines.h"
|
||||
#include "CounterStyleManager.h"
|
||||
#include "mozilla/dom/HTMLDetailsElement.h"
|
||||
#include "mozilla/dom/HTMLSummaryElement.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/RestyleManager.h"
|
||||
#include "mozilla/ServoStyleSet.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
#include "nsFileControlFrame.h"
|
||||
#include "nsMathMLContainerFrame.h"
|
||||
#include "nsSelectsAreaFrame.h"
|
||||
|
||||
#include "nsBidiPresUtils.h"
|
||||
|
||||
@@ -95,7 +87,7 @@ static void MarkAllDescendantLinesDirty(nsBlockFrame* aBlock) {
|
||||
|
||||
static void MarkSameFloatManagerLinesDirty(nsBlockFrame* aBlock) {
|
||||
nsBlockFrame* blockWithFloatMgr = aBlock;
|
||||
while (!blockWithFloatMgr->HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
while (!blockWithFloatMgr->HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
nsBlockFrame* bf = do_QueryFrame(blockWithFloatMgr->GetParent());
|
||||
if (!bf) {
|
||||
break;
|
||||
@@ -436,13 +428,6 @@ nsBlockFrame* NS_NewBlockFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
|
||||
return new (aPresShell) nsBlockFrame(aStyle, aPresShell->GetPresContext());
|
||||
}
|
||||
|
||||
nsBlockFrame* NS_NewBlockFormattingContext(PresShell* aPresShell,
|
||||
ComputedStyle* aComputedStyle) {
|
||||
nsBlockFrame* blockFrame = NS_NewBlockFrame(aPresShell, aComputedStyle);
|
||||
blockFrame->AddStateBits(NS_BLOCK_STATIC_BFC);
|
||||
return blockFrame;
|
||||
}
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsBlockFrame)
|
||||
|
||||
nsBlockFrame::~nsBlockFrame() = default;
|
||||
@@ -1184,7 +1169,7 @@ static LogicalSize CalculateContainingBlockSizeForAbsolutes(
|
||||
*/
|
||||
static const nsBlockFrame* GetAsLineClampDescendant(const nsIFrame* aFrame) {
|
||||
if (const nsBlockFrame* block = do_QueryFrame(aFrame)) {
|
||||
if (!block->HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
if (!block->HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
@@ -1201,7 +1186,7 @@ static bool IsLineClampRoot(const nsBlockFrame* aFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aFrame->HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
if (!aFrame->HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3925,7 +3910,7 @@ bool nsBlockFrame::IsSelfEmpty() {
|
||||
// Blocks which are margin-roots (including inline-blocks) cannot be treated
|
||||
// as empty for margin-collapsing and other purposes. They're more like
|
||||
// replaced elements.
|
||||
if (HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
if (HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5249,7 +5234,7 @@ void nsBlockFrame::SplitFloat(BlockReflowState& aState, nsIFrame* aFloat,
|
||||
}
|
||||
|
||||
aState.AppendPushedFloatChain(nextInFlow);
|
||||
if (MOZ_LIKELY(!HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) ||
|
||||
if (MOZ_LIKELY(!HasAnyStateBits(NS_BLOCK_BFC)) ||
|
||||
MOZ_UNLIKELY(IsTrueOverflowContainer())) {
|
||||
aState.mReflowStatus.SetOverflowIncomplete();
|
||||
} else {
|
||||
@@ -6497,6 +6482,20 @@ nsBlockInFlowLineIterator::nsBlockInFlowLineIterator(nsBlockFrame* aFrame,
|
||||
*aFoundValidLine = FindValidLine();
|
||||
}
|
||||
|
||||
static bool AnonymousBoxIsBFC(const ComputedStyle* aStyle) {
|
||||
switch (aStyle->GetPseudoType()) {
|
||||
case PseudoStyleType::fieldsetContent:
|
||||
case PseudoStyleType::columnContent:
|
||||
case PseudoStyleType::buttonContent:
|
||||
case PseudoStyleType::cellContent:
|
||||
case PseudoStyleType::scrolledContent:
|
||||
case PseudoStyleType::anonymousItem:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool StyleEstablishesBFC(const ComputedStyle* aStyle) {
|
||||
// paint/layout containment boxes and multi-column containers establish an
|
||||
// independent formatting context.
|
||||
@@ -6504,11 +6503,59 @@ static bool StyleEstablishesBFC(const ComputedStyle* aStyle) {
|
||||
// https://drafts.csswg.org/css-contain/#containment-layout
|
||||
// https://drafts.csswg.org/css-align/#distribution-block
|
||||
// https://drafts.csswg.org/css-multicol/#columns
|
||||
return aStyle->StyleDisplay()->IsContainPaint() ||
|
||||
aStyle->StyleDisplay()->IsContainLayout() ||
|
||||
const auto* disp = aStyle->StyleDisplay();
|
||||
return disp->IsContainPaint() || disp->IsContainLayout() ||
|
||||
disp->DisplayInside() == StyleDisplayInside::FlowRoot ||
|
||||
disp->IsAbsolutelyPositionedStyle() || disp->IsFloatingStyle() ||
|
||||
aStyle->StylePosition()->mAlignContent.primary !=
|
||||
StyleAlignFlags::NORMAL ||
|
||||
aStyle->GetPseudoType() == PseudoStyleType::columnContent;
|
||||
aStyle->IsRootElementStyle() || AnonymousBoxIsBFC(aStyle);
|
||||
}
|
||||
|
||||
static bool EstablishesBFC(const nsBlockFrame* aFrame) {
|
||||
if (aFrame->HasAnyClassFlag(LayoutFrameClassFlags::BlockFormattingContext)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nsIFrame* parent = aFrame->GetParent()) {
|
||||
if (parent->IsFieldSetFrame()) {
|
||||
// A rendered legend always establishes a new formatting context, and so
|
||||
// does the fieldset content frame, so we can just return true here.
|
||||
// https://html.spec.whatwg.org/#rendered-legend
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto wm = aFrame->GetWritingMode();
|
||||
const auto parentWM = parent->GetWritingMode();
|
||||
if (wm.GetBlockDir() != parentWM.GetBlockDir() ||
|
||||
wm.IsVerticalSideways() != parentWM.IsVerticalSideways()) {
|
||||
// If a box has a different writing-mode value than its containing block
|
||||
// [...] if the box is a block container, then it establishes a new block
|
||||
// formatting context.
|
||||
// https://drafts.csswg.org/css-writing-modes/#block-flow
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (aFrame->IsColumnSpan()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aFrame->IsSuppressedScrollableBlockForPrint()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto* style = aFrame->Style();
|
||||
if (style->GetPseudoType() == PseudoStyleType::marker) {
|
||||
if (aFrame->GetParent() &&
|
||||
aFrame->GetParent()->StyleList()->mListStylePosition ==
|
||||
StyleListStylePosition::Outside) {
|
||||
// An outside ::marker needs to be an independent formatting context
|
||||
// to avoid being influenced by the float manager etc.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return StyleEstablishesBFC(style);
|
||||
}
|
||||
|
||||
void nsBlockFrame::DidSetComputedStyle(ComputedStyle* aOldStyle) {
|
||||
@@ -6517,24 +6564,16 @@ void nsBlockFrame::DidSetComputedStyle(ComputedStyle* aOldStyle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If NS_BLOCK_STATIC_BFC flag was set when the frame was initialized, it
|
||||
// remains set during the lifetime of the frame and always forces it to be
|
||||
// treated as a BFC, independently of the value of NS_BLOCK_DYNAMIC_BFC.
|
||||
// Consequently, we don't bother invalidating or updating that latter flag.
|
||||
if (HasAnyStateBits(NS_BLOCK_STATIC_BFC)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool isBFC = StyleEstablishesBFC(Style());
|
||||
if (StyleEstablishesBFC(aOldStyle) != isBFC) {
|
||||
const bool isBFC = EstablishesBFC(this);
|
||||
if (HasAnyStateBits(NS_BLOCK_BFC) != isBFC) {
|
||||
if (MaybeHasFloats()) {
|
||||
// If the frame contains floats, this update may change their float
|
||||
// manager. Be safe by dirtying all descendant lines of the nearest
|
||||
// ancestor's float manager.
|
||||
RemoveStateBits(NS_BLOCK_DYNAMIC_BFC);
|
||||
RemoveStateBits(NS_BLOCK_BFC);
|
||||
MarkSameFloatManagerLinesDirty(this);
|
||||
}
|
||||
AddOrRemoveStateBits(NS_BLOCK_DYNAMIC_BFC, isBFC);
|
||||
AddOrRemoveStateBits(NS_BLOCK_BFC, isBFC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7837,35 +7876,15 @@ void nsBlockFrame::ChildIsDirty(nsIFrame* aChild) {
|
||||
nsContainerFrame::ChildIsDirty(aChild);
|
||||
}
|
||||
|
||||
static bool AlwaysEstablishesBFC(const nsBlockFrame* aFrame) {
|
||||
switch (aFrame->Type()) {
|
||||
case LayoutFrameType::ColumnSetWrapper:
|
||||
// CSS Multi-column level 1 section 2: A multi-column container
|
||||
// establishes a new block formatting context, as per CSS 2.1 section
|
||||
// 9.4.1.
|
||||
case LayoutFrameType::ComboboxControl:
|
||||
return true;
|
||||
case LayoutFrameType::Block:
|
||||
return static_cast<const nsFileControlFrame*>(do_QueryFrame(aFrame)) ||
|
||||
// Ensure that the options inside the select aren't expanded by
|
||||
// right floats outside the select.
|
||||
static_cast<const nsSelectsAreaFrame*>(do_QueryFrame(aFrame)) ||
|
||||
// See bug 1373767 and bug 353894.
|
||||
static_cast<const nsMathMLmathBlockFrame*>(do_QueryFrame(aFrame));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void nsBlockFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) {
|
||||
// These are all the block specific frame bits, they are copied from
|
||||
// the prev-in-flow to a newly created next-in-flow, except for the
|
||||
// NS_BLOCK_FLAGS_NON_INHERITED_MASK bits below.
|
||||
constexpr nsFrameState NS_BLOCK_FLAGS_MASK =
|
||||
NS_BLOCK_BFC_STATE_BITS | NS_BLOCK_CLIP_PAGINATED_OVERFLOW |
|
||||
NS_BLOCK_HAS_FIRST_LETTER_STYLE | NS_BLOCK_FRAME_HAS_OUTSIDE_MARKER |
|
||||
NS_BLOCK_HAS_FIRST_LETTER_CHILD | NS_BLOCK_FRAME_HAS_INSIDE_MARKER;
|
||||
NS_BLOCK_BFC | NS_BLOCK_HAS_FIRST_LETTER_STYLE |
|
||||
NS_BLOCK_FRAME_HAS_OUTSIDE_MARKER | NS_BLOCK_HAS_FIRST_LETTER_CHILD |
|
||||
NS_BLOCK_FRAME_HAS_INSIDE_MARKER;
|
||||
|
||||
// This is the subset of NS_BLOCK_FLAGS_MASK that is NOT inherited
|
||||
// by default. They should only be set on the first-in-flow.
|
||||
@@ -7887,37 +7906,12 @@ void nsBlockFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
AddStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
}
|
||||
|
||||
// A display:flow-root box establishes a block formatting context.
|
||||
//
|
||||
// If a box has a different writing-mode value than its containing block:
|
||||
// ...
|
||||
// If the box is a block container, then it establishes a new block
|
||||
// formatting context.
|
||||
// (https://drafts.csswg.org/css-writing-modes/#block-flow)
|
||||
//
|
||||
// If the box has contain: paint or contain:layout (or contain:strict),
|
||||
// then it should also establish a formatting context.
|
||||
//
|
||||
// Per spec, a column-span always establishes a new block formatting context.
|
||||
//
|
||||
// Other more specific frame types also always establish a BFC.
|
||||
//
|
||||
if (StyleDisplay()->mDisplay == StyleDisplay::FlowRoot ||
|
||||
(GetParent() &&
|
||||
(GetWritingMode().GetBlockDir() !=
|
||||
GetParent()->GetWritingMode().GetBlockDir() ||
|
||||
GetWritingMode().IsVerticalSideways() !=
|
||||
GetParent()->GetWritingMode().IsVerticalSideways())) ||
|
||||
IsColumnSpan() || AlwaysEstablishesBFC(this)) {
|
||||
AddStateBits(NS_BLOCK_STATIC_BFC);
|
||||
}
|
||||
|
||||
if (StyleEstablishesBFC(Style())) {
|
||||
AddStateBits(NS_BLOCK_DYNAMIC_BFC);
|
||||
if (EstablishesBFC(this)) {
|
||||
AddStateBits(NS_BLOCK_BFC);
|
||||
}
|
||||
|
||||
if (HasAnyStateBits(NS_FRAME_FONT_INFLATION_CONTAINER) &&
|
||||
HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
|
||||
}
|
||||
}
|
||||
@@ -7970,11 +7964,6 @@ void nsBlockFrame::SetMarkerFrameForListItem(nsIFrame* aMarkerFrame) {
|
||||
SetProperty(InsideMarkerProperty(), aMarkerFrame);
|
||||
AddStateBits(NS_BLOCK_FRAME_HAS_INSIDE_MARKER);
|
||||
} else {
|
||||
if (nsBlockFrame* marker = do_QueryFrame(aMarkerFrame)) {
|
||||
// An outside ::marker needs to be an independent formatting context
|
||||
// to avoid being influenced by the float manager etc.
|
||||
marker->AddStateBits(NS_BLOCK_STATIC_BFC);
|
||||
}
|
||||
SetProperty(OutsideMarkerProperty(),
|
||||
new (PresShell()) nsFrameList(aMarkerFrame, aMarkerFrame));
|
||||
AddStateBits(NS_BLOCK_FRAME_HAS_OUTSIDE_MARKER);
|
||||
@@ -8175,7 +8164,7 @@ void nsBlockFrame::CheckFloats(BlockReflowState& aState) {
|
||||
void nsBlockFrame::IsMarginRoot(bool* aBStartMarginRoot,
|
||||
bool* aBEndMarginRoot) {
|
||||
nsIFrame* parent = GetParent();
|
||||
if (!HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
if (!HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
if (!parent || parent->IsFloatContainingBlock()) {
|
||||
*aBStartMarginRoot = false;
|
||||
*aBEndMarginRoot = false;
|
||||
@@ -8202,14 +8191,14 @@ bool nsBlockFrame::BlockNeedsFloatManager(nsIFrame* aBlock) {
|
||||
NS_ASSERTION(aBlock->IsBlockFrameOrSubclass(), "aBlock must be a block");
|
||||
|
||||
nsIFrame* parent = aBlock->GetParent();
|
||||
return aBlock->HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS) ||
|
||||
return aBlock->HasAnyStateBits(NS_BLOCK_BFC) ||
|
||||
(parent && !parent->IsFloatContainingBlock());
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool nsBlockFrame::BlockCanIntersectFloats(nsIFrame* aFrame) {
|
||||
return aFrame->IsBlockFrameOrSubclass() && !aFrame->IsReplaced() &&
|
||||
!aFrame->HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS);
|
||||
!aFrame->HasAnyStateBits(NS_BLOCK_BFC);
|
||||
}
|
||||
|
||||
// Note that this width can vary based on the vertical position.
|
||||
|
||||
@@ -275,7 +275,7 @@ void nsBlockReflowContext::ReflowBlock(const LogicalRect& aSpace,
|
||||
tI = space.LineLeft(mWritingMode, mContainerSize);
|
||||
tB = mBCoord;
|
||||
|
||||
if (!mFrame->HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
if (!mFrame->HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
aFrameRI.mBlockDelta =
|
||||
mOuterReflowInput.mBlockDelta + mBCoord - aLine->BStart();
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ struct nsFlowAreaRect {
|
||||
/**
|
||||
* nsFloatManager is responsible for implementing CSS's rules for
|
||||
* positioning floats. An nsFloatManager object is created during reflow for
|
||||
* any block with NS_BLOCK_BFC_STATE_BITS. During reflow, the float manager for
|
||||
* the nearest such ancestor block is found in ReflowInput::mFloatManager.
|
||||
* any block with NS_BLOCK_BFC. During reflow, the float manager for the nearest
|
||||
* such ancestor block is found in ReflowInput::mFloatManager.
|
||||
*
|
||||
* According to the line-relative mappings in CSS Writing Modes spec [1],
|
||||
* line-right and line-left are calculated with respect to the writing mode
|
||||
|
||||
@@ -541,41 +541,30 @@ FRAME_STATE_BIT(Block, 21, NS_BLOCK_HAS_PUSHED_FLOATS)
|
||||
// 2. This indicates that a block frame should create its own float manager.
|
||||
// This is required by each block frame that can contain floats. The float
|
||||
// manager is used to reserve space for the floated frames.
|
||||
FRAME_STATE_BIT(Block, 22, NS_BLOCK_STATIC_BFC)
|
||||
FRAME_STATE_BIT(Block, 22, NS_BLOCK_BFC)
|
||||
|
||||
// This is the same as NS_BLOCK_STATIC_BFC but can be updated dynamically after
|
||||
// the frame construction (e.g. paint/layout containment).
|
||||
// FIXME(bug 1874823): Try and merge this and NS_BLOCK_STATIC_BFC.
|
||||
FRAME_STATE_BIT(Block, 23, NS_BLOCK_DYNAMIC_BFC)
|
||||
FRAME_STATE_BIT(Block, 23, NS_BLOCK_HAS_LINE_CURSOR)
|
||||
|
||||
// For testing the relevant bits on a block formatting context:
|
||||
#define NS_BLOCK_BFC_STATE_BITS (NS_BLOCK_STATIC_BFC | NS_BLOCK_DYNAMIC_BFC)
|
||||
FRAME_STATE_BIT(Block, 24, NS_BLOCK_HAS_OVERFLOW_LINES)
|
||||
|
||||
FRAME_STATE_BIT(Block, 24, NS_BLOCK_HAS_LINE_CURSOR)
|
||||
|
||||
FRAME_STATE_BIT(Block, 25, NS_BLOCK_HAS_OVERFLOW_LINES)
|
||||
|
||||
FRAME_STATE_BIT(Block, 26, NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS)
|
||||
FRAME_STATE_BIT(Block, 25, NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS)
|
||||
|
||||
// Set on any block that has descendant frames in the normal
|
||||
// flow with 'clear' set to something other than 'none'
|
||||
// (including <BR CLEAR="..."> frames)
|
||||
FRAME_STATE_BIT(Block, 27, NS_BLOCK_HAS_CLEAR_CHILDREN)
|
||||
|
||||
// NS_BLOCK_CLIP_PAGINATED_OVERFLOW is only set in paginated prescontexts, on
|
||||
// blocks which were forced to not have scrollframes but still need to clip
|
||||
// the display of their kids.
|
||||
FRAME_STATE_BIT(Block, 28, NS_BLOCK_CLIP_PAGINATED_OVERFLOW)
|
||||
FRAME_STATE_BIT(Block, 26, NS_BLOCK_HAS_CLEAR_CHILDREN)
|
||||
|
||||
// NS_BLOCK_HAS_FIRST_LETTER_STYLE means that the block has first-letter style,
|
||||
// even if it has no actual first-letter frame among its descendants.
|
||||
FRAME_STATE_BIT(Block, 29, NS_BLOCK_HAS_FIRST_LETTER_STYLE)
|
||||
FRAME_STATE_BIT(Block, 27, NS_BLOCK_HAS_FIRST_LETTER_STYLE)
|
||||
|
||||
// NS_BLOCK_FRAME_HAS_OUTSIDE_MARKER and NS_BLOCK_FRAME_HAS_INSIDE_MARKER
|
||||
// means the block has an associated ::marker frame, they are mutually
|
||||
// exclusive.
|
||||
FRAME_STATE_BIT(Block, 30, NS_BLOCK_FRAME_HAS_OUTSIDE_MARKER)
|
||||
FRAME_STATE_BIT(Block, 31, NS_BLOCK_FRAME_HAS_INSIDE_MARKER)
|
||||
FRAME_STATE_BIT(Block, 28, NS_BLOCK_FRAME_HAS_OUTSIDE_MARKER)
|
||||
FRAME_STATE_BIT(Block, 29, NS_BLOCK_FRAME_HAS_INSIDE_MARKER)
|
||||
|
||||
// bits 30 and 31 free.
|
||||
|
||||
// NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS indicates that exactly one line in this
|
||||
// block has the LineClampEllipsis flag set, and that such a line must be found
|
||||
|
||||
@@ -57,10 +57,6 @@ nsresult NS_NewAttributeContent(nsNodeInfoManager* aNodeInfoManager,
|
||||
nsContainerFrame* NS_NewSelectsAreaFrame(mozilla::PresShell* aPresShell,
|
||||
mozilla::ComputedStyle* aStyle);
|
||||
|
||||
// Create a block formatting context blockframe
|
||||
nsBlockFrame* NS_NewBlockFormattingContext(mozilla::PresShell* aPresShell,
|
||||
mozilla::ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame* NS_NewBRFrame(mozilla::PresShell* aPresShell,
|
||||
mozilla::ComputedStyle* aStyle);
|
||||
|
||||
|
||||
@@ -2484,7 +2484,7 @@ bool nsIFrame::CanBeDynamicReflowRoot() const {
|
||||
|
||||
// If we participate in a container's block reflow context, or margins
|
||||
// can collapse through us, we can't be a dynamic reflow root.
|
||||
if (IsBlockFrameOrSubclass() && !HasAnyStateBits(NS_BLOCK_BFC_STATE_BITS)) {
|
||||
if (IsBlockFrameOrSubclass() && !HasAnyStateBits(NS_BLOCK_BFC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -11563,11 +11563,24 @@ nsIFrame::PhysicalAxes nsIFrame::ShouldApplyOverflowClipping(
|
||||
return PhysicalAxes::None;
|
||||
}
|
||||
|
||||
// If we're paginated and a block, and have NS_BLOCK_CLIP_PAGINATED_OVERFLOW
|
||||
// set, then we want to clip our overflow.
|
||||
bool clip = HasAnyStateBits(NS_BLOCK_CLIP_PAGINATED_OVERFLOW) &&
|
||||
PresContext()->IsPaginated() && IsBlockFrame();
|
||||
return clip ? PhysicalAxes::Both : PhysicalAxes::None;
|
||||
return IsSuppressedScrollableBlockForPrint() ? PhysicalAxes::Both
|
||||
: PhysicalAxes::None;
|
||||
}
|
||||
|
||||
bool nsIFrame::IsSuppressedScrollableBlockForPrint() const {
|
||||
// This condition needs to match the suppressScrollFrame logic in the frame
|
||||
// constructor.
|
||||
if (!PresContext()->IsPaginated() || !IsBlockFrame() ||
|
||||
!StyleDisplay()->IsScrollableOverflow() ||
|
||||
!StyleDisplay()->IsBlockOutsideStyle() ||
|
||||
mContent->IsInNativeAnonymousSubtree()) {
|
||||
return false;
|
||||
}
|
||||
if (auto* element = Element::FromNode(mContent);
|
||||
element && PresContext()->ElementWouldPropagateScrollStyles(*element)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nsIFrame::HasUnreflowedContainerQueryAncestor() const {
|
||||
|
||||
@@ -562,6 +562,8 @@ enum class LayoutFrameClassFlags : uint16_t {
|
||||
SupportsContainLayoutAndPaint = 1 << 13,
|
||||
// Whether this frame class supports the `aspect-ratio` property.
|
||||
SupportsAspectRatio = 1 << 14,
|
||||
// Whether this frame class is always a BFC.
|
||||
BlockFormattingContext = 1 << 15,
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(LayoutFrameClassFlags)
|
||||
@@ -3035,6 +3037,9 @@ class nsIFrame : public nsQueryFrame {
|
||||
nsSize OverflowClipMargin(PhysicalAxes aClipAxes) const;
|
||||
// Returns the axes on which this frame should apply overflow clipping.
|
||||
PhysicalAxes ShouldApplyOverflowClipping(const nsStyleDisplay* aDisp) const;
|
||||
// Returns whether this frame is a block that was supposed to be a
|
||||
// scrollframe, but that was suppressed for print.
|
||||
bool IsSuppressedScrollableBlockForPrint() const;
|
||||
|
||||
/**
|
||||
* Helper method used by block reflow to identify runs of text so
|
||||
|
||||
Reference in New Issue
Block a user