Bug 1159042 - p5. Add NS_FRAME_DYNAMIC_REFLOW_ROOT on frames that we can dynamically make reflow roots - r=dholbert

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
L. David Baron 2018-12-11 20:33:29 +00:00
Родитель 16349625aa
Коммит cabd72af5d
3 изменённых файлов: 94 добавлений и 3 удалений

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

@ -403,6 +403,7 @@ void ReflowInput::Init(nsPresContext* aPresContext,
InitConstraints(aPresContext, cbSize, aBorder, aPadding, type);
InitResizeFlags(aPresContext, type);
InitDynamicReflowRoot();
nsIFrame* parent = mFrame->GetParent();
if (parent && (parent->GetStateBits() & NS_FRAME_IN_CONSTRAINED_BSIZE) &&
@ -795,6 +796,92 @@ void ReflowInput::InitResizeFlags(nsPresContext* aPresContext,
}
}
static inline bool IsIntrinsicKeyword(const nsStyleCoord& aCoord) {
if (aCoord.GetUnit() != eStyleUnit_Enumerated) {
return false;
}
// All of the keywords except for '-moz-available' depend on intrinsic sizes.
return aCoord.GetIntValue() != NS_STYLE_WIDTH_AVAILABLE;
}
void ReflowInput::InitDynamicReflowRoot() {
auto display = mStyleDisplay->mDisplay;
if (mFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
nsStyleDisplay::IsRubyDisplayType(display) ||
mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE ||
display == StyleDisplay::Table || display == StyleDisplay::TableCaption ||
display == StyleDisplay::InlineTable ||
(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 = true;
// 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 nsStyleCoord& width = mStylePosition->mWidth;
const nsStyleCoord& height = mStylePosition->mHeight;
if (!width.IsCoordPercentCalcUnit() || width.HasPercent() ||
!height.IsCoordPercentCalcUnit() || height.HasPercent() ||
IsIntrinsicKeyword(mStylePosition->mMinWidth) ||
IsIntrinsicKeyword(mStylePosition->mMaxWidth) ||
IsIntrinsicKeyword(mStylePosition->mMinHeight) ||
IsIntrinsicKeyword(mStylePosition->mMaxHeight) ||
((mStylePosition->mMinWidth.GetUnit() == eStyleUnit_Auto ||
mStylePosition->mMinHeight.GetUnit() == eStyleUnit_Auto) &&
mFrame->IsFlexOrGridItem())) {
canBeDynamicReflowRoot = false;
}
if (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 nsStyleCoord& flexBasis = mStylePosition->mFlexBasis;
if (flexBasis.GetUnit() != eStyleUnit_Auto &&
(!flexBasis.IsCoordPercentCalcUnit() || flexBasis.HasPercent())) {
canBeDynamicReflowRoot = false;
}
}
if (!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;
} else {
MOZ_ASSERT(mFrame->IsAbsPosContainingBlock(),
"we need the frame to be both an abs-pos and fixed-pos cb");
}
// 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->IsFrameOfType(nsIFrame::eBlockFrame) &&
!mFrame->HasAllStateBits(NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT)) {
canBeDynamicReflowRoot = false;
}
if (canBeDynamicReflowRoot) {
mFrame->AddStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
} else {
mFrame->RemoveStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
}
}
nscoord ReflowInput::GetContainingBlockContentISize(
WritingMode aWritingMode) const {
if (!mCBReflowInput) {

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

@ -982,6 +982,7 @@ struct ReflowInput : public SizeComputationInput {
void InitCBReflowInput();
void InitResizeFlags(nsPresContext* aPresContext,
mozilla::LayoutFrameType aFrameType);
void InitDynamicReflowRoot();
void InitConstraints(nsPresContext* aPresContext,
const mozilla::LogicalSize& aContainingBlockSize,

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

@ -248,8 +248,9 @@ FRAME_STATE_BIT(Generic, 43, NS_FRAME_SVG_LAYOUT)
// ancestor.
FRAME_STATE_BIT(Generic, 44, NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)
// Bits 45 is currently unused, but be kind and check with bug 1465474
// first please :-)
// If this bit is set, then reflow may be dispatched from the current
// frame instead of the root frame.
FRAME_STATE_BIT(Generic, 45, NS_FRAME_DYNAMIC_REFLOW_ROOT)
// This bit indicates that we're tracking visibility for this frame, and that
// the frame has a VisibilityStateProperty property.
@ -309,7 +310,9 @@ FRAME_STATE_BIT(Generic, 59, NS_FRAME_IS_IN_SINGLE_CHAR_MI)
// NOTE: Bits 20-31 and 60-63 of the frame state are reserved for specific
// frame classes.
// NOTE: Currently unused and available bit(s): 45.
// NOTE: No more unused bits. If needed, investigate removing obsolete bits by
// adjusting logic, or moving infrequently-used bits elsewhere. If more space
// for frame state is still needed, look for bit field gaps in nsIFrame.
// == Frame state bits that apply to box frames ===============================