mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-27 15:55:16 +00:00
Bug 1623390 - Factor out the CanBeDynamicReflowRoot bits. r=dholbert
This is cleaner and allows to reuse this logic for some experiments I have :) Differential Revision: https://phabricator.services.mozilla.com/D67354 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
63cacb2ad9
commit
eca8fd9020
@ -23,7 +23,6 @@
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsIPercentBSizeObserver.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsFontInflationData.h"
|
||||
#include "StickyScrollContainer.h"
|
||||
#include "nsIFrameInlines.h"
|
||||
@ -745,109 +744,8 @@ void ReflowInput::InitResizeFlags(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SizeOrMaxSize>
|
||||
static inline bool IsIntrinsicKeyword(const SizeOrMaxSize& aSize) {
|
||||
if (!aSize.IsExtremumLength()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All of the keywords except for '-moz-available' depend on intrinsic sizes.
|
||||
return aSize.AsExtremumLength() != StyleExtremumLength::MozAvailable;
|
||||
}
|
||||
|
||||
static bool AreDynamicReflowRootsEnabled() {
|
||||
static bool sAreDynamicReflowRootsEnabled;
|
||||
static bool sIsPrefCached = false;
|
||||
|
||||
if (!sIsPrefCached) {
|
||||
sIsPrefCached = true;
|
||||
Preferences::AddBoolVarCache(&sAreDynamicReflowRootsEnabled,
|
||||
"layout.dynamic-reflow-roots.enabled");
|
||||
}
|
||||
return sAreDynamicReflowRootsEnabled;
|
||||
}
|
||||
|
||||
void ReflowInput::InitDynamicReflowRoot() {
|
||||
auto display = mStyleDisplay->mDisplay;
|
||||
if (mFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
|
||||
nsStyleDisplay::IsRubyDisplayType(display) ||
|
||||
mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE ||
|
||||
nsStyleDisplay::DisplayInside(display) == StyleDisplayInside::Table ||
|
||||
(mFrame->GetParent() && mFrame->GetParent()->IsXULBoxFrame())) {
|
||||
// We have a display type where 'width' and 'height' don't actually
|
||||
// set the width or height (i.e., the size depends on content).
|
||||
NS_ASSERTION(!(mFrame->GetStateBits() & NS_FRAME_DYNAMIC_REFLOW_ROOT),
|
||||
"should not have dynamic reflow root bit");
|
||||
return;
|
||||
}
|
||||
|
||||
bool canBeDynamicReflowRoot = AreDynamicReflowRootsEnabled();
|
||||
|
||||
// We can't do this if our used 'width' and 'height' might be influenced by
|
||||
// content.
|
||||
// FIXME: For display:block, we should probably optimize inline-size
|
||||
// being auto.
|
||||
// FIXME: Other flex and grid cases?
|
||||
const auto& width = mStylePosition->mWidth;
|
||||
const auto& height = mStylePosition->mHeight;
|
||||
if (canBeDynamicReflowRoot &&
|
||||
(!width.IsLengthPercentage() || width.HasPercent() ||
|
||||
!height.IsLengthPercentage() || height.HasPercent() ||
|
||||
IsIntrinsicKeyword(mStylePosition->mMinWidth) ||
|
||||
IsIntrinsicKeyword(mStylePosition->mMaxWidth) ||
|
||||
IsIntrinsicKeyword(mStylePosition->mMinHeight) ||
|
||||
IsIntrinsicKeyword(mStylePosition->mMaxHeight) ||
|
||||
((mStylePosition->mMinWidth.IsAuto() ||
|
||||
mStylePosition->mMinHeight.IsAuto()) &&
|
||||
mFrame->IsFlexOrGridItem()))) {
|
||||
canBeDynamicReflowRoot = false;
|
||||
}
|
||||
|
||||
if (canBeDynamicReflowRoot && mFrame->IsFlexItem()) {
|
||||
// If our flex-basis is 'auto', it'll defer to 'width' (or 'height') which
|
||||
// we've already checked. Otherwise, it preempts them, so we need to
|
||||
// perform the same "could-this-value-be-influenced-by-content" checks that
|
||||
// we performed for 'width' and 'height' above.
|
||||
const auto& flexBasis = mStylePosition->mFlexBasis;
|
||||
if (!flexBasis.IsAuto()) {
|
||||
if (!flexBasis.IsSize() || !flexBasis.AsSize().IsLengthPercentage() ||
|
||||
flexBasis.AsSize().HasPercent()) {
|
||||
canBeDynamicReflowRoot = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canBeDynamicReflowRoot && !mFrame->IsFixedPosContainingBlock()) {
|
||||
// We can't treat this frame as a reflow root, since dynamic changes
|
||||
// to absolutely-positioned frames inside of it require that we
|
||||
// reflow the placeholder before we reflow the absolutely positioned
|
||||
// frame.
|
||||
// FIXME: Alternatively, we could sort the reflow roots in
|
||||
// PresShell::ProcessReflowCommands by depth in the tree, from
|
||||
// deepest to least deep. However, for performance (FIXME) we
|
||||
// should really be sorting them in the opposite order!
|
||||
canBeDynamicReflowRoot = false;
|
||||
}
|
||||
|
||||
// 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 (canBeDynamicReflowRoot && mFrame->IsBlockFrameOrSubclass() &&
|
||||
!mFrame->HasAllStateBits(NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT)) {
|
||||
canBeDynamicReflowRoot = false;
|
||||
}
|
||||
|
||||
// Subgrids are never reflow roots, but 'contain:layout/paint' prevents
|
||||
// creating a subgrid in the first place.
|
||||
if (canBeDynamicReflowRoot &&
|
||||
(mStylePosition->mGridTemplateColumns.IsSubgrid() ||
|
||||
mStylePosition->mGridTemplateRows.IsSubgrid()) &&
|
||||
!(mStyleDisplay->IsContainLayout() || mStyleDisplay->IsContainPaint())) {
|
||||
// NOTE: we could check that 'display' of our content's primary frame is
|
||||
// '[inline-]grid' here but that's probably not worth it in practice.
|
||||
canBeDynamicReflowRoot = false;
|
||||
}
|
||||
|
||||
if (canBeDynamicReflowRoot) {
|
||||
if (mFrame->CanBeDynamicReflowRoot()) {
|
||||
mFrame->AddStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
|
||||
} else {
|
||||
mFrame->RemoveStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
|
||||
|
@ -2455,6 +2455,99 @@ already_AddRefed<ComputedStyle> nsIFrame::ComputeSelectionStyle(
|
||||
*element, PseudoStyleType::selection, Style());
|
||||
}
|
||||
|
||||
template <typename SizeOrMaxSize>
|
||||
static inline bool IsIntrinsicKeyword(const SizeOrMaxSize& aSize) {
|
||||
if (!aSize.IsExtremumLength()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All of the keywords except for '-moz-available' depend on intrinsic sizes.
|
||||
return aSize.AsExtremumLength() != StyleExtremumLength::MozAvailable;
|
||||
}
|
||||
|
||||
bool nsIFrame::CanBeDynamicReflowRoot() const {
|
||||
if (!StaticPrefs::layout_dynamic_reflow_roots_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& display = *StyleDisplay();
|
||||
if (IsFrameOfType(nsIFrame::eLineParticipant) ||
|
||||
nsStyleDisplay::IsRubyDisplayType(display.mDisplay) ||
|
||||
display.DisplayOutside() == StyleDisplayOutside::InternalTable ||
|
||||
display.DisplayInside() == StyleDisplayInside::Table ||
|
||||
(GetParent() && GetParent()->IsXULBoxFrame())) {
|
||||
// We have a display type where 'width' and 'height' don't actually set the
|
||||
// width or height (i.e., the size depends on content).
|
||||
MOZ_ASSERT(!HasAnyStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT),
|
||||
"should not have dynamic reflow root bit");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can't serve as a dynamic reflow root if our used 'width' and 'height'
|
||||
// might be influenced by content.
|
||||
//
|
||||
// FIXME: For display:block, we should probably optimize inline-size: auto.
|
||||
// FIXME: Other flex and grid cases?
|
||||
auto& pos = *StylePosition();
|
||||
const auto& width = pos.mWidth;
|
||||
const auto& height = pos.mHeight;
|
||||
if (!width.IsLengthPercentage() || width.HasPercent() ||
|
||||
!height.IsLengthPercentage() || height.HasPercent() ||
|
||||
IsIntrinsicKeyword(pos.mMinWidth) || IsIntrinsicKeyword(pos.mMaxWidth) ||
|
||||
IsIntrinsicKeyword(pos.mMinHeight) ||
|
||||
IsIntrinsicKeyword(pos.mMaxHeight) ||
|
||||
((pos.mMinWidth.IsAuto() || pos.mMinHeight.IsAuto()) &&
|
||||
IsFlexOrGridItem())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If our flex-basis is 'auto', it'll defer to 'width' (or 'height') which
|
||||
// we've already checked. Otherwise, it preempts them, so we need to
|
||||
// perform the same "could-this-value-be-influenced-by-content" checks that
|
||||
// we performed for 'width' and 'height' above.
|
||||
if (IsFlexItem()) {
|
||||
const auto& flexBasis = pos.mFlexBasis;
|
||||
if (!flexBasis.IsAuto()) {
|
||||
if (!flexBasis.IsSize() || !flexBasis.AsSize().IsLengthPercentage() ||
|
||||
flexBasis.AsSize().HasPercent()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsFixedPosContainingBlock()) {
|
||||
// We can't treat this frame as a reflow root, since dynamic changes
|
||||
// to absolutely-positioned frames inside of it require that we
|
||||
// reflow the placeholder before we reflow the absolutely positioned
|
||||
// frame.
|
||||
// FIXME: Alternatively, we could sort the reflow roots in
|
||||
// PresShell::ProcessReflowCommands by depth in the tree, from
|
||||
// deepest to least deep. However, for performance (FIXME) we
|
||||
// should really be sorting them in the opposite order!
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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() &&
|
||||
!HasAllStateBits(NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Subgrids are never reflow roots, but 'contain:layout/paint' prevents
|
||||
// creating a subgrid in the first place.
|
||||
if (pos.mGridTemplateColumns.IsSubgrid() ||
|
||||
pos.mGridTemplateRows.IsSubgrid()) {
|
||||
// NOTE: we could check that 'display' of our parent's primary frame is
|
||||
// '[inline-]grid' here but that's probably not worth it in practice.
|
||||
if (!display.IsContainLayout() && !display.IsContainPaint()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Refreshes each content's frame
|
||||
*********************************************************/
|
||||
|
@ -862,6 +862,8 @@ class nsIFrame : public nsQueryFrame {
|
||||
*/
|
||||
nsContainerFrame* GetParent() const { return mParent; }
|
||||
|
||||
bool CanBeDynamicReflowRoot() const;
|
||||
|
||||
/**
|
||||
* Gets the parent of a frame, using the parent of the placeholder for
|
||||
* out-of-flow frames.
|
||||
|
Loading…
x
Reference in New Issue
Block a user