Bug 1449838 part 1: Add utility function nsFlexContainerFrame::IsItemInlineAxisMainAxis(). r?mats
This patch doesn't affect behavior - it's just refactoring / de-duplicating.
(The refactored function does include some new "legacy box" code, just for
completeness & to ensure that the included assertion passes. But beyond the
assertion, that new code isn't exercised right now -- this function's only
callsites are skipped if the NS_STATE_FLEX_IS_EMULATING_LEGACY_BOX state-bit is
set on the container. Hence, this patch still doesn't affect behavior, even
though it's adding some new logic in the refactored-out function.)
MozReview-Commit-ID: G5aCzwTwkTa
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -1818,16 +1818,20 @@ FlexItem::FlexItem(ReflowInput& aFlexIte
// mNeedsMinSizeAutoResolution is initialized in CheckForMinSizeAuto()
// mAlignSelf, see below
{
MOZ_ASSERT(mFrame, "expecting a non-null child frame");
MOZ_ASSERT(!mFrame->IsPlaceholderFrame(),
"placeholder frames should not be treated as flex items");
MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
"out-of-flow frames should not be treated as flex items");
+ MOZ_ASSERT(mIsInlineAxisMainAxis ==
+ nsFlexContainerFrame::IsItemInlineAxisMainAxis(mFrame),
+ "public API should be consistent with internal state (about "
+ "whether flex item's inline axis is flex container's main axis)");
const ReflowInput* containerRS = aFlexItemReflowInput.mParentReflowInput;
if (IsLegacyBox(containerRS->mFrame)) {
// For -webkit-{inline-}box and -moz-{inline-}box, we need to:
// (1) Use prefixed "box-align" instead of "align-items" to determine the
// container's cross-axis alignment behavior.
// (2) Suppress the ability for flex items to override that with their own
// cross-axis alignment. (The legacy box model doesn't support this.)
@@ -4376,16 +4380,51 @@ nsFlexContainerFrame::GetFlexFrameWithCo
flexFrame->HasProperty(FlexContainerInfo()),
"The state bit should've made our forced-reflow "
"generate a FlexContainerInfo object");
}
}
return flexFrame;
}
+/* static */
+bool
+nsFlexContainerFrame::IsItemInlineAxisMainAxis(nsIFrame* aFrame)
+{
+ MOZ_ASSERT(aFrame && aFrame->IsFlexItem(), "expecting arg to be a flex item");
+ const WritingMode flexItemWM = aFrame->GetWritingMode();
+ const nsIFrame* flexContainer = aFrame->GetParent();
+
+ if (IsLegacyBox(flexContainer)) {
+ // For legacy boxes, the main axis is determined by "box-orient", and we can
+ // just directly check if that's vertical, and compare that to whether the
+ // item's WM is also vertical:
+ bool boxOrientIsVertical =
+ (flexContainer->StyleXUL()->mBoxOrient == StyleBoxOrient::Vertical);
+ return flexItemWM.IsVertical() == boxOrientIsVertical;
+ }
+
+ // For modern CSS flexbox, we get our return value by asking two questions
+ // and comparing their answers.
+ // Question 1: does aFrame have the same inline axis as its flex container?
+ bool itemInlineAxisIsParallelToParent =
+ !flexItemWM.IsOrthogonalTo(flexContainer->GetWritingMode());
+
+ // Question 2: is aFrame's flex container row-oriented? (This tells us
+ // whether the flex container's main axis is its inline axis.)
+ auto flexDirection = flexContainer->StylePosition()->mFlexDirection;
+ bool flexContainerIsRowOriented =
+ flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
+ flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
+
+ // aFrame's inline axis is its flex container's main axis IFF the above
+ // questions have the same answer.
+ return flexContainerIsRowOriented == itemInlineAxisIsParallelToParent;
+}
+
void
nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus,
nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent,
nsTArray<StrutInfo>& aStruts,
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -192,16 +192,31 @@ public:
/**
* Return aFrame as a flex frame after ensuring it has computed flex info.
* @return nullptr if aFrame is null or doesn't have a flex frame
* as its content insertion frame.
* @note this might destroy layout/style data since it may flush layout.
*/
static nsFlexContainerFrame* GetFlexFrameWithComputedInfo(nsIFrame* aFrame);
+ /**
+ * Given a frame for a flex item, this method returns true IFF that flex
+ * item's inline axis is the same as (i.e. not orthogonal to) its flex
+ * container's main axis.
+ *
+ * (This method is only intended to be used from external
+ * callers. Inside of flex reflow code, FlexItem::IsInlineAxisMainAxis() is
+ * equivalent & more optimal.)
+ *
+ * @param aFrame a flex item (must return true from IsFlexItem)
+ * @return true iff aFrame's inline axis is the same as (i.e. not orthogonal
+ * to) its flex container's main axis. Otherwise, false.
+ */
+ static bool IsItemInlineAxisMainAxis(nsIFrame* aFrame);
+
protected:
// Protected constructor & destructor
explicit nsFlexContainerFrame(ComputedStyle* aStyle)
: nsContainerFrame(aStyle, kClassID)
, mBaselineFromLastReflow(NS_INTRINSIC_WIDTH_UNKNOWN)
, mLastBaselineFromLastReflow(NS_INTRINSIC_WIDTH_UNKNOWN)
{}
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5667,35 +5667,20 @@ nsFrame::ComputeSize(gfxContext*
!parentFrame->HasAnyStateBits(NS_STATE_FLEX_IS_EMULATING_LEGACY_BOX) &&
!HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
// This bool only gets set (and used) if isFlexItem is true.
// It indicates (for flex items) whether we're using their flex-basis for the
// item's own ISize property vs. for its BSize property.
bool usingFlexBasisForISize = false;
if (isFlexItem) {
// Flex items use their "flex-basis" property in place of their main-size
- // property (e.g. "width") for sizing purposes, *unless* they have
- // "flex-basis:auto", in which case they use their main-size property after
- // all.
- uint32_t flexDirection = GetParent()->StylePosition()->mFlexDirection;
- const bool flexContainerIsRowOriented =
- flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
- flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
- const bool inlineAxisSameAsParent =
- !aWM.IsOrthogonalTo(parentFrame->GetWritingMode());
-
- // If parent is row-oriented, its main axis (i.e. the flex-basis axis) is
- // its own inline axis. So if it's row oriented and our own inline axis
- // is the same as our parent's, then we'll be using flex-basis in place
- // of our _ISize_ sizing property.
- // Otherwise, we'll be using flex-basis for our _BSize_ sizing property
- // (unless both conditions are false, in which case we flip back around to
- // using our ISize sizing property).
+ // property for sizing purposes, *unless* they have "flex-basis:auto", in
+ // which case they use their main-size property after all.
usingFlexBasisForISize =
- (flexContainerIsRowOriented == inlineAxisSameAsParent);
+ nsFlexContainerFrame::IsItemInlineAxisMainAxis(this);
// NOTE: The logic here should match the similar chunk for determining
// inlineStyleCoord and blockStyleCoord in
// nsFrame::ComputeSizeWithIntrinsicDimensions().
const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
if (flexBasis->GetUnit() != eStyleUnit_Auto) {
// Override whichever styleCoord is in flex container's main axis:
(usingFlexBasisForISize ? inlineStyleCoord : blockStyleCoord) =
@@ -5907,27 +5892,18 @@ nsFrame::ComputeSizeWithIntrinsicDimensi
Maybe<nsStyleCoord> imposedMainSizeStyleCoord;
// If this is a flex item, and we're measuring its cross size after flexing
// to resolve its main size, then we need to use the resolved main size
// that the container provides to us *instead of* the main-size coordinate
// from our style struct. (Otherwise, we'll be using an irrelevant value in
// the aspect-ratio calculations below.)
if (isFlexItem) {
- uint32_t flexDirection =
- GetParent()->StylePosition()->mFlexDirection;
- const bool flexContainerIsRowOriented =
- flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
- flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
- const bool inlineAxisSameAsParent =
- !aWM.IsOrthogonalTo(parentFrame->GetWritingMode());
-
- // (See explanatory comment in similar code within ComputeSize.)
usingFlexBasisForISize =
- (flexContainerIsRowOriented == inlineAxisSameAsParent);
+ nsFlexContainerFrame::IsItemInlineAxisMainAxis(this);
// If FlexItemMainSizeOverride frame-property is set, then that means the
// flex container is imposing a main-size on this flex item for it to use
// as its size in the container's main axis.
bool didImposeMainSize;
nscoord imposedMainSize =
GetProperty(nsIFrame::FlexItemMainSizeOverride(), &didImposeMainSize);
if (didImposeMainSize) {